General Setup


Create a new analysis directories.

- general directory

- stains directory

- for plots

- for output of summary results

- for baseline tables

- for genetic analyses

- for Cox regression results
source("scripts/functions.R")
source("scripts/pack03.packages.R")

* General packages...
trying URL 'https://bioconductor.org/packages/3.21/bioc/bin/macosx/big-sur-x86_64/contrib/4.5/limma_3.64.1.tgz'
Content type 'application/x-gzip' length 3148172 bytes (3.0 MB)
==================================================
downloaded 3.0 MB

The downloaded binary packages are in
    /var/folders/mm/b4fx9qss7t79pb95gn3k6grh0000gq/T//Rtmpp5gMOF/downloaded_packages
Update all/some/none? [a/s/n]: 
n
Today = format(as.Date(as.POSIXlt(Sys.time())), "%Y%m%d")
Today.Report = format(as.Date(as.POSIXlt(Sys.time())), "%A, %B %d, %Y")
source("scripts/colors.R")

ERA-CVD ‘druggable-MI-targets’

For the ERA-CVD ‘druggable-MI-targets’ project (grantnumber: 01KL1802) we performed two related RNA sequencing (RNAseq) experiments:

  1. conventional (‘bulk’) RNAseq using RNA extracted from carotid plaque samples, n ± 700. As of Wednesday, July 02, 2025 all samples have been selected and RNA has been extracted; quality control (QC) was performed and we have a dataset of 635 samples.

  2. single-cell RNAseq (scRNAseq) of at least n = 40 samples (20 females, 20 males). As of Wednesday, July 02, 2025 data is available of 40 samples (3 females, 15 males), we are extending sampling to get more female samples.

Plaque samples are derived from carotid endarterectomies as part of the Athero-Express Biobank Study which is an ongoing study in the UMC Utrecht.

Background

Here we map the PHENOMICL_downstream to single-cells from the plaques.

Targets

Here we obtain data from the PHENOMICL_downstream in plaques.

library(openxlsx)

gene_list_df <- read.xlsx(paste0(PROJECT_loc, "/targets/targets.xlsx"), sheet = "Genes")

gene_list <- unlist(gene_list_df$Gene)
gene_list
 [1] "SCGB3A2"  "LIX1"     "IGSF9B"   "ND6"      "ALB"      "OR10A4"   "RASEF"    "NEDD4"    "TRIM49D1"
[10] "TCL1A"    "ND4L"     "ATP8"     "FBXO15"   "F5"       "TMEM212"  "PTPRD"    "CYP46A1"  "OR2T33"  
[19] "SORBS2"   "ITGA7"    "RNASE1"   "FOS"      "HMOX1"    "LAPTM5"   "MMP9"     "SIGLEC1"  "FTL"     
[28] "CD14"     "HCST"     "TIMP3"    "CCL2"     "SAT1"     "CD163"    "PTGDS"    "LGALS9"   "ACKR1"   
[37] "NT5DC2"   "TGFBI"    "C1QC"     "S100A9"  

Load data

First we will load the data:

  • scRNAseq experimental data and rename the cell types.
  • Athero-Express clinical data.

Here we load the latest dataset from our Athero-Express single-cell RNA experiment.


# load(paste0(AESCRNA_loc, "/20210811.46.patients.KP.RData"))
# scRNAseqData <- seuset
# rm(seuset)
# 
# saveRDS(scRNAseqData, paste0(AESCRNA_loc, "/20210811.46.patients.KP.RDS"))

scRNAseqData <- readRDS(paste0(AESCRNA_loc, "/20210811.46.patients.KP.RDS"))

scRNAseqData
An object of class Seurat 
36147 features across 4948 samples within 2 assays 
Active assay: RNA (20111 features, 0 variable features)
 3 layers present: counts, data, scale.data
 1 other assay present: SCT
 2 dimensional reductions calculated: pca, umap

The naming/classification is based on a combination conventional markers. We do not claim to know the exact identity of each cell, rather we refer to cells as ‘KIT+ Mast cells”-like cells. Likewise we refer to the cell clusters as ’communities’ of cells that exhibit similar properties, i.e. similar defining markers (e.g. KIT).

We will rename the cell types to human readable names.

### change names for clarity
backup.scRNAseqData = scRNAseqData
# get the old names to change to new names
UMAPPlot(scRNAseqData, label = FALSE, pt.size = 1.25, label.size = 4, group.by = "ident")

unique(scRNAseqData@active.ident)
 [1] CD3+ T Cells I                                 CD3+ T Cells IV                               
 [3] CD34+ Endothelial Cells I                      CD3+ T Cells V                                
 [5] CD3+CD56+ NK Cells II                          CD3+ T Cells VI                               
 [7] CD68+IL18+TLR4+TREM2+ Resident macrophages     CD3+CD56+ NK Cells I                          
 [9] ACTA2+ Smooth Muscle Cells                     CD3+ T Cells II                               
[11] FOXP3+ T Cells                                 CD34+ Endothelial Cells II                    
[13] CD3+ T Cells III                               CD68+CD1C+ Dendritic Cells                    
[15] CD68+CASP1+IL1B+SELL+ Inflammatory macrophages CD79A+ Class-switched Memory B Cells          
[17] CD68+ABCA1+OLR1+TREM2+ Foam Cells              CD68+KIT+ Mast Cells                          
[19] CD68+CD4+ Monocytes                            CD79+ Plasma B Cells                          
20 Levels: CD3+ T Cells I CD3+ T Cells II CD3+ T Cells III ... CD79+ Plasma B Cells
celltypes <- c("CD68+CD4+ Monocytes" = "CD68+CD4+ Mono", 
               "CD68+IL18+TLR4+TREM2+ Resident macrophages" = "CD68+IL18+TLR4+TREM2+ MRes", 
               "CD68+CD1C+ Dendritic Cells" = "CD68+CD1C+ DC",
               "CD68+CASP1+IL1B+SELL+ Inflammatory macrophages" = "CD68+CASP1+IL1B+SELL MInf",
               "CD68+ABCA1+OLR1+TREM2+ Foam Cells" = "CD68+ABCA1+OLR1+TREM2+ FC",
               
               # T-cells
               "CD3+ T Cells I" = "CD3+ TC I",
               "CD3+ T Cells II" = "CD3+ TC II", 
               "CD3+ T Cells III" = "CD3+ TC III", 
               "CD3+ T Cells IV" = "CD3+ TC IV", 
               "CD3+ T Cells V" = "CD3+ TC V", 
               "CD3+ T Cells VI" = "CD3+ TC VI", 
               "FOXP3+ T Cells" = "FOXP3+ TC",
               
               # Endothelial cells
               "CD34+ Endothelial Cells I" = "CD34+ EC I", 
               "CD34+ Endothelial Cells II" = "CD34+ EC II", 
               
               # SMC
               "ACTA2+ Smooth Muscle Cells" = "ACTA2+ SMC", 
               
               # NK Cells
               "CD3+CD56+ NK Cells I" = "CD3+CD56+ NK I",
               "CD3+CD56+ NK Cells II" = "CD3+CD56+ NK II",
               # Mast
               "CD68+KIT+ Mast Cells" = "CD68+KIT+ MC",
               
               "CD79A+ Class-switched Memory B Cells" = "CD79A+ BCmem", 
               "CD79+ Plasma B Cells" = "CD79+ BCplasma")

scRNAseqData <- Seurat::RenameIdents(object = scRNAseqData, 
                                       celltypes)
UMAPPlot(scRNAseqData, label = TRUE, pt.size = 1.25, label.size = 4, group.by = "ident",
         repel = TRUE)

Clinical data

Loading the Athero-Express clinical data.

# AEDB.CEA <- readRDS(file = paste0(OUT_loc, "/", Today,".",PROJECTNAME,".AEDB.CEA.RDS"))
AEDB.CEA <- readRDS(file = paste0(OUT_loc, "/20241219.",PROJECTNAME,".AEDB.CEA.RDS"))
# Baseline table variables
basetable_vars = c("Hospital", "ORyear", "Artery_summary",
                   "Age", "Gender", 
                   # "TC_finalCU", "LDL_finalCU", "HDL_finalCU", "TG_finalCU", 
                   "TC_final", "LDL_final", "HDL_final", "TG_final", 
                   # "hsCRP_plasma",
                   "systolic", "diastoli", "GFR_MDRD", "BMI", 
                   "KDOQI", "BMI_WHO",
                   "SmokerStatus", "AlcoholUse",
                   "DiabetesStatus", 
                   "Hypertension.selfreport", "Hypertension.selfreportdrug", "Hypertension.composite", "Hypertension.drugs", 
                   "Med.anticoagulants", "Med.all.antiplatelet", "Med.Statin.LLD", 
                   "Stroke_Dx", "sympt", "Symptoms.5G", "AsymptSympt", "AsymptSympt2G",
                   "Symptoms.Update2G", "Symptoms.Update3G", "indexsymptoms_latest_4g",
                   "restenos", "stenose", 
                   "CAD_history", "PAOD", "Peripheral.interv", 
                   "EP_composite", "EP_composite_time", "EP_major", "EP_major_time",
                   "MAC_rankNorm", "SMC_rankNorm", "Macrophages.bin", "SMC.bin",
                   "Neutrophils_rankNorm", "MastCells_rankNorm",
                   "IPH.bin", "VesselDensity_rankNorm",
                   "Calc.bin", "Collagen.bin", 
                   "Fat.bin_10", "Fat.bin_40", "OverallPlaquePhenotype", "Plaque_Vulnerability_Index",
                   "PCSK9_plasma", "PCSK9_plasma_rankNorm")

basetable_bin = c("Gender",  "Artery_summary",
                  "KDOQI", "BMI_WHO",
                  "SmokerStatus", "AlcoholUse",
                  "DiabetesStatus", 
                  "Hypertension.selfreport", "Hypertension.selfreportdrug", "Hypertension.composite", "Hypertension.drugs", 
                  "Med.anticoagulants", "Med.all.antiplatelet", "Med.Statin.LLD", 
                  "Stroke_Dx", "sympt", "Symptoms.5G", "AsymptSympt", "AsymptSympt2G",
                  "Symptoms.Update2G", "Symptoms.Update3G", "indexsymptoms_latest_4g",
                  "restenos", "stenose",
                  "CAD_history", "PAOD", "Peripheral.interv", 
                  "EP_major", "EP_composite", "Macrophages.bin", "SMC.bin",
                  "IPH.bin", 
                  "Calc.bin", "Collagen.bin", 
                  "Fat.bin_10", "Fat.bin_40", "OverallPlaquePhenotype", "Plaque_Vulnerability_Index")
# basetable_bin

basetable_con = basetable_vars[!basetable_vars %in% basetable_bin]
# basetable_con

AESCRNA: baseline characteristics

Preparation

metadata <- scRNAseqData@meta.data %>% as_tibble() %>% separate(orig.ident, c("Patient", NA))
scRNAseqDataMeta <- metadata %>% distinct(Patient, .keep_all = TRUE)

scRNAseqDataMetaAE <- merge(scRNAseqDataMeta, AEDB.CEA, by.x = "Patient", by.y = "STUDY_NUMBER", sort = FALSE, all.x = TRUE)
dim(scRNAseqDataMetaAE)
[1]   46 1237
# Replace missing data 
# Ref: https://cran.r-project.org/web/packages/naniar/vignettes/replace-with-na.html
require(naniar)

na_strings <- c("NA", "N A", "N / A", "N/A", "N/ A", 
                "Not Available", "Not available", 
                "missing", 
                "-999", "-99", 
                "No data available/missing", "No data available/Missing")
# Then you write ~.x %in% na_strings - which reads as “does this value occur in the list of NA strings”.

scRNAseqDataMetaAE %>%
  replace_with_na_all(condition = ~.x %in% na_strings)
cat("====================================================================================================")
====================================================================================================
cat("SELECTION THE SHIZZLE")
SELECTION THE SHIZZLE
cat("- sanity checking PRIOR to selection")
- sanity checking PRIOR to selection
library(data.table)
require(labelled)
ae.gender <- to_factor(scRNAseqDataMetaAE$Gender)
ae.hospital <- to_factor(scRNAseqDataMetaAE$Hospital)
table(ae.gender, ae.hospital, dnn = c("Sex", "Hospital"), useNA = "ifany")
        Hospital
Sex      St. Antonius, Nieuwegein UMC Utrecht <NA>
  female                        0          18    0
  male                          0          26    0
  <NA>                          0           0    2
ae.artery <- to_factor(scRNAseqDataMetaAE$Artery_summary)
table(ae.artery, ae.gender, dnn = c("Sex", "Artery"), useNA = "ifany")
                                                                                         Artery
Sex                                                                                       female male
  No artery known (yet), no surgery (patient ill, died, exited study), re-numbered to AAA      0    0
  carotid (left & right)                                                                      18   25
  femoral/iliac (left, right or both sides)                                                    0    0
  other carotid arteries (common, external)                                                    0    1
  carotid bypass and injury (left, right or both sides)                                        0    0
  aneurysmata (carotid & femoral)                                                              0    0
  aorta                                                                                        0    0
  other arteries (renal, popliteal, vertebral)                                                 0    0
  femoral bypass, angioseal and injury (left, right or both sides)                             0    0
  <NA>                                                                                         0    0
                                                                                         Artery
Sex                                                                                       <NA>
  No artery known (yet), no surgery (patient ill, died, exited study), re-numbered to AAA    0
  carotid (left & right)                                                                     0
  femoral/iliac (left, right or both sides)                                                  0
  other carotid arteries (common, external)                                                  0
  carotid bypass and injury (left, right or both sides)                                      0
  aneurysmata (carotid & femoral)                                                            0
  aorta                                                                                      0
  other arteries (renal, popliteal, vertebral)                                               0
  femoral bypass, angioseal and injury (left, right or both sides)                           0
  <NA>                                                                                       2
ae.ic <- to_factor(scRNAseqDataMetaAE$informedconsent)
table(ae.ic, ae.gender, useNA = "ifany")
                                                                                                 ae.gender
ae.ic                                                                                             female
  missing                                                                                              0
  no, died                                                                                             0
  yes                                                                                                  9
  yes, health treatment when possible                                                                  5
  yes, no health treatment                                                                             2
  yes, no health treatment, no commercial business                                                     1
  yes, no tissue, no commerical business                                                               0
  yes, no tissue, no questionnaires, no medical info, no commercial business                           0
  yes, no questionnaires, no health treatment, no commercial business                                  0
  yes, no questionnaires, health treatment when possible                                               0
  yes, no tissue, no questionnaires, no health treatment, no commerical business                       0
  yes, no health treatment, no medical info, no commercial business                                    0
  yes, no tissue, no questionnaires, no health treatment, no medical info, no commercial business      0
  yes, no questionnaires, no health treatment                                                          0
  yes, no tissue, no health treatment                                                                  0
  yes, no tissue, no questionnaires                                                                    0
  yes, no tissue, health treatment when possible                                                       0
  yes, no tissue                                                                                       0
  yes, no commerical business                                                                          1
  yes, health treatment when possible, no commercial business                                          0
  yes, no medical info, no commercial business                                                         0
  yes, no questionnaires                                                                               0
  yes, no tissue, no questionnaires, no health treatment, no medical info                              0
  yes, no tissue, no questionnaires, no health treatment, no commercial business                       0
  yes, no medical info                                                                                 0
  yes, no questionnaires, no commercial business                                                       0
  yes, no questionnaires, no health treatment, no medical info                                         0
  yes, no questionnaires, health treatment when possible, no commercial business                       0
  yes,  no health treatment, no medical info                                                           0
  no, doesn't want to                                                                                  0
  no, unable to sign                                                                                   0
  no, no reaction                                                                                      0
  no, lost                                                                                             0
  no, too old                                                                                          0
  yes, no medical info, health treatment when possible                                                 0
  no (never asked for IC because there was no tissue)                                                  0
  yes, no medical info, no commercial business, health treatment when possible                         0
  no, endpoint                                                                                         0
  wil niets invullen, wel alles gebruiken                                                              0
  second informed concents: yes, no commercial business                                                0
  nooit geincludeerd                                                                                   0
  yes, not outside EU                                                                                  0
  yes, no DNA                                                                                          0
  <NA>                                                                                                 0
                                                                                                 ae.gender
ae.ic                                                                                             male
  missing                                                                                            0
  no, died                                                                                           0
  yes                                                                                               14
  yes, health treatment when possible                                                                7
  yes, no health treatment                                                                           2
  yes, no health treatment, no commercial business                                                   2
  yes, no tissue, no commerical business                                                             0
  yes, no tissue, no questionnaires, no medical info, no commercial business                         0
  yes, no questionnaires, no health treatment, no commercial business                                0
  yes, no questionnaires, health treatment when possible                                             0
  yes, no tissue, no questionnaires, no health treatment, no commerical business                     0
  yes, no health treatment, no medical info, no commercial business                                  0
  yes, no tissue, no questionnaires, no health treatment, no medical info, no commercial business    0
  yes, no questionnaires, no health treatment                                                        0
  yes, no tissue, no health treatment                                                                0
  yes, no tissue, no questionnaires                                                                  0
  yes, no tissue, health treatment when possible                                                     0
  yes, no tissue                                                                                     0
  yes, no commerical business                                                                        1
  yes, health treatment when possible, no commercial business                                        0
  yes, no medical info, no commercial business                                                       0
  yes, no questionnaires                                                                             0
  yes, no tissue, no questionnaires, no health treatment, no medical info                            0
  yes, no tissue, no questionnaires, no health treatment, no commercial business                     0
  yes, no medical info                                                                               0
  yes, no questionnaires, no commercial business                                                     0
  yes, no questionnaires, no health treatment, no medical info                                       0
  yes, no questionnaires, health treatment when possible, no commercial business                     0
  yes,  no health treatment, no medical info                                                         0
  no, doesn't want to                                                                                0
  no, unable to sign                                                                                 0
  no, no reaction                                                                                    0
  no, lost                                                                                           0
  no, too old                                                                                        0
  yes, no medical info, health treatment when possible                                               0
  no (never asked for IC because there was no tissue)                                                0
  yes, no medical info, no commercial business, health treatment when possible                       0
  no, endpoint                                                                                       0
  wil niets invullen, wel alles gebruiken                                                            0
  second informed concents: yes, no commercial business                                              0
  nooit geincludeerd                                                                                 0
  yes, not outside EU                                                                                0
  yes, no DNA                                                                                        0
  <NA>                                                                                               0
                                                                                                 ae.gender
ae.ic                                                                                             <NA>
  missing                                                                                            0
  no, died                                                                                           0
  yes                                                                                                0
  yes, health treatment when possible                                                                0
  yes, no health treatment                                                                           0
  yes, no health treatment, no commercial business                                                   0
  yes, no tissue, no commerical business                                                             0
  yes, no tissue, no questionnaires, no medical info, no commercial business                         0
  yes, no questionnaires, no health treatment, no commercial business                                0
  yes, no questionnaires, health treatment when possible                                             0
  yes, no tissue, no questionnaires, no health treatment, no commerical business                     0
  yes, no health treatment, no medical info, no commercial business                                  0
  yes, no tissue, no questionnaires, no health treatment, no medical info, no commercial business    0
  yes, no questionnaires, no health treatment                                                        0
  yes, no tissue, no health treatment                                                                0
  yes, no tissue, no questionnaires                                                                  0
  yes, no tissue, health treatment when possible                                                     0
  yes, no tissue                                                                                     0
  yes, no commerical business                                                                        0
  yes, health treatment when possible, no commercial business                                        0
  yes, no medical info, no commercial business                                                       0
  yes, no questionnaires                                                                             0
  yes, no tissue, no questionnaires, no health treatment, no medical info                            0
  yes, no tissue, no questionnaires, no health treatment, no commercial business                     0
  yes, no medical info                                                                               0
  yes, no questionnaires, no commercial business                                                     0
  yes, no questionnaires, no health treatment, no medical info                                       0
  yes, no questionnaires, health treatment when possible, no commercial business                     0
  yes,  no health treatment, no medical info                                                         0
  no, doesn't want to                                                                                0
  no, unable to sign                                                                                 0
  no, no reaction                                                                                    0
  no, lost                                                                                           0
  no, too old                                                                                        0
  yes, no medical info, health treatment when possible                                               0
  no (never asked for IC because there was no tissue)                                                0
  yes, no medical info, no commercial business, health treatment when possible                       0
  no, endpoint                                                                                       0
  wil niets invullen, wel alles gebruiken                                                            0
  second informed concents: yes, no commercial business                                              0
  nooit geincludeerd                                                                                 0
  yes, not outside EU                                                                                0
  yes, no DNA                                                                                        0
  <NA>                                                                                               2
rm(ae.gender, ae.hospital, ae.artery, ae.ic)


scRNAseqDataMetaAE.all <- subset(scRNAseqDataMetaAE,
                                 (Artery_summary == "carotid (left & right)" | Artery_summary == "other carotid arteries (common, external)" ) & # we only want carotids
                                   informedconsent != "missing" & # we are really strict in selecting based on 'informed consent'!
                                   informedconsent != "no, died" &
                                   informedconsent != "yes, no tissue, no commerical business" &
                                   informedconsent != "yes, no tissue, no questionnaires, no medical info, no commercial business" &
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no commerical business" &
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no medical info, no commercial business" &
                                   informedconsent != "yes, no tissue, no health treatment" &
                                   informedconsent != "yes, no tissue, no questionnaires" &
                                   informedconsent != "yes, no tissue, health treatment when possible" &
                                   informedconsent != "yes, no tissue" &
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no medical info" &
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no commercial business" &
                                   informedconsent != "no, doesn't want to" &
                                   informedconsent != "no, unable to sign" &
                                   informedconsent != "no, no reaction" &
                                   informedconsent != "no, lost" &
                                   informedconsent != "no, too old" &
                                   informedconsent != "yes, no medical info, health treatment when possible" & 
                                   informedconsent != "no (never asked for IC because there was no tissue)" &
                                   informedconsent != "no, endpoint" &
                                   informedconsent != "nooit geincludeerd" & 
                                   informedconsent != "yes, no health treatment, no commercial business" & # IMPORTANT: since we are sharing with a commercial party
                                   informedconsent != "yes, no tissue, no commerical business" & 
                                   informedconsent != "yes, no tissue, no questionnaires, no medical info, no commercial business" & 
                                   informedconsent != "yes, no questionnaires, no health treatment, no commercial business" & 
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no commerical business" & 
                                   informedconsent != "yes, no health treatment, no medical info, no commercial business" & 
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no medical info, no commercial business" & 
                                   informedconsent != "yes, no commerical business" & 
                                   informedconsent != "yes, health treatment when possible, no commercial business" & 
                                   informedconsent != "yes, no medical info, no commercial business" & 
                                   informedconsent != "yes, no tissue, no questionnaires, no health treatment, no commercial business" & 
                                   informedconsent != "yes, no questionnaires, no commercial business" & 
                                   informedconsent != "yes, no questionnaires, health treatment when possible, no commercial business" & 
                                   informedconsent != "second informed concents: yes, no commercial business")
# scRNAseqDataMetaAE.all[1:10, 1:10]
dim(scRNAseqDataMetaAE.all)
[1]   39 1237
# DT::datatable(scRNAseqDataMetaAE.all)

Baseline AESCRNA Study

Showing the baseline table for the scRNAseq data in 39 CEA patients with informed consent.

cat("===========================================================================================")
===========================================================================================
cat("CREATE BASELINE TABLE")
CREATE BASELINE TABLE
# Create baseline tables
# http://rstudio-pubs-static.s3.amazonaws.com/13321_da314633db924dc78986a850813a50d5.html
scRNAseqDataMetaAE.all.tableOne = print(CreateTableOne(vars = basetable_vars, 
                                                  factorVars = basetable_bin,
                                                  strata = "Gender",
                                                  data = scRNAseqDataMetaAE.all, includeNA = TRUE), 
                                   nonnormal = c(), 
                                   quote = FALSE, showAllLevels = TRUE,
                                   format = "p", 
                                   contDigits = 3)
                                 Stratified by Gender
                                  level                                     female             
  n                                                                               16           
  Hospital (%)                    St. Antonius, Nieuwegein                       0.0           
                                  UMC Utrecht                                  100.0           
  ORyear (%)                      No data available/missing                      0.0           
                                  2002                                           0.0           
                                  2003                                           0.0           
                                  2004                                           0.0           
                                  2005                                           0.0           
                                  2006                                           0.0           
                                  2007                                           0.0           
                                  2008                                           0.0           
                                  2009                                           0.0           
                                  2010                                           0.0           
                                  2011                                           0.0           
                                  2012                                           0.0           
                                  2013                                           0.0           
                                  2014                                           0.0           
                                  2015                                           0.0           
                                  2016                                           0.0           
                                  2017                                           0.0           
                                  2018                                          25.0           
                                  2019                                          43.8           
                                  2020                                          25.0           
                                  2021                                           6.2           
                                  2022                                           0.0           
  Artery_summary (%)              carotid (left & right)                       100.0           
                                  other carotid arteries (common, external)      0.0           
  Age (mean (SD))                                                             70.500 (8.017)   
  Gender (%)                      female                                       100.0           
                                  male                                           0.0           
  TC_final (mean (SD))                                                         5.180 (1.628)   
  LDL_final (mean (SD))                                                        3.444 (1.076)   
  HDL_final (mean (SD))                                                        1.200 (0.153)   
  TG_final (mean (SD))                                                         2.111 (0.818)   
  systolic (mean (SD))                                                       152.938 (30.732)  
  diastoli (mean (SD))                                                        81.375 (19.145)  
  GFR_MDRD (mean (SD))                                                        69.529 (22.867)  
  BMI (mean (SD))                                                             25.920 (4.284)   
  KDOQI (%)                       Normal kidney function                        12.5           
                                  CKD 2 (Mild)                                  50.0           
                                  CKD 3 (Moderate)                              31.2           
                                  <NA>                                           6.2           
  BMI_WHO (%)                     Underweight                                    0.0           
                                  Normal                                        43.8           
                                  Overweight                                    31.2           
                                  Obese                                         18.8           
                                  <NA>                                           6.2           
  SmokerStatus (%)                Current smoker                                31.2           
                                  Ex-smoker                                     50.0           
                                  Never smoked                                  12.5           
                                  <NA>                                           6.2           
  AlcoholUse (%)                  No                                            43.8           
                                  Yes                                           50.0           
                                  <NA>                                           6.2           
  DiabetesStatus (%)              Control (no Diabetes Dx/Med)                  87.5           
                                  Diabetes                                      12.5           
  Hypertension.selfreport (%)     no                                             0.0           
                                  yes                                           87.5           
                                  <NA>                                          12.5           
  Hypertension.selfreportdrug (%) no                                             0.0           
                                  yes                                           93.8           
                                  <NA>                                           6.2           
  Hypertension.composite (%)      no                                             6.2           
                                  yes                                           93.8           
  Hypertension.drugs (%)          no                                            12.5           
                                  yes                                           81.2           
                                  <NA>                                           6.2           
  Med.anticoagulants (%)          no                                            87.5           
                                  yes                                            0.0           
                                  <NA>                                          12.5           
  Med.all.antiplatelet (%)        no                                            18.8           
                                  yes                                           75.0           
                                  <NA>                                           6.2           
  Med.Statin.LLD (%)              no                                            25.0           
                                  yes                                           68.8           
                                  <NA>                                           6.2           
  Stroke_Dx (%)                   No stroke diagnosed                           56.2           
                                  Stroke diagnosed                              43.8           
  sympt (%)                       Asymptomatic                                   0.0           
                                  TIA                                           31.2           
                                  minor stroke                                  25.0           
                                  Major stroke                                  12.5           
                                  Amaurosis fugax                               12.5           
                                  Retinal infarction                             6.2           
                                  Symptomatic, but aspecific symtoms             6.2           
                                  retinal infarction                             0.0           
                                  Ocular ischemic syndrome                       6.2           
  Symptoms.5G (%)                 Asymptomatic                                   0.0           
                                  Ocular                                        18.8           
                                  Other                                          6.2           
                                  Retinal infarction                             6.2           
                                  Stroke                                        37.5           
                                  TIA                                           31.2           
  AsymptSympt (%)                 Asymptomatic                                   0.0           
                                  Ocular and others                             31.2           
                                  Symptomatic                                   68.8           
  AsymptSympt2G (%)               Asymptomatic                                   0.0           
                                  Symptomatic                                  100.0           
  Symptoms.Update2G (%)           Asymptomatic                                   0.0           
                                  Symptomatic                                  100.0           
  Symptoms.Update3G (%)           Asymptomatic                                   0.0           
                                  Symptomatic                                  100.0           
  indexsymptoms_latest_4g (%)     asymp                                          0.0           
                                  ocular                                        25.0           
                                  TIA                                           37.5           
                                  stroke                                        37.5           
  restenos (%)                    de novo                                      100.0           
  stenose (%)                     0-49%                                          6.2           
                                  50-70%                                         0.0           
                                  70-90%                                        62.5           
                                  90-99%                                        25.0           
                                  70-99%                                         6.2           
  CAD_history (%)                 No history CAD                                81.2           
                                  History CAD                                   18.8           
  PAOD (%)                        no                                            81.2           
                                  yes                                           18.8           
  Peripheral.interv (%)           no                                            75.0           
                                  yes                                           25.0           
  EP_composite (%)                No composite endpoints                        81.2           
                                  Composite endpoints                           12.5           
                                  <NA>                                           6.2           
  EP_composite_time (mean (SD))                                             1302.998 (4867.095)
  EP_major (%)                    No major events (endpoints)                   87.5           
                                  Major events (endpoints)                       6.2           
                                  <NA>                                           6.2           
  EP_major_time (mean (SD))                                                 1303.167 (4867.046)
  Macrophages.bin (%)             no/minor                                       0.0           
                                  <NA>                                         100.0           
  SMC.bin (%)                     moderate/heavy                                 0.0           
                                  <NA>                                         100.0           
  Calc.bin (%)                    no/minor                                       0.0           
                                  <NA>                                         100.0           
  Collagen.bin (%)                moderate/heavy                                 0.0           
                                  <NA>                                         100.0           
  Fat.bin_10 (%)                   >10%                                          0.0           
                                  <NA>                                         100.0           
  Fat.bin_40 (%)                  <40%                                           0.0           
                                  <NA>                                         100.0           
  OverallPlaquePhenotype (%)      fibroatheromatous                              0.0           
                                  <NA>                                         100.0           
  Plaque_Vulnerability_Index (%)  0                                            100.0           
                                  1                                              0.0           
                                 Stratified by Gender
                                  male             p      test
  n                                    23                     
  Hospital (%)                        0.0             NaN     
                                    100.0                     
  ORyear (%)                          0.0             NaN     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
                                     69.6                     
                                     30.4                     
                                      0.0                     
                                      0.0                     
                                      0.0                     
  Artery_summary (%)                 95.7           1.000     
                                      4.3                     
  Age (mean (SD))                  73.174 (8.294)   0.322     
  Gender (%)                          0.0          <0.001     
                                    100.0                     
  TC_final (mean (SD))              4.153 (0.800)   0.037     
  LDL_final (mean (SD))             2.244 (0.687)   0.002     
  HDL_final (mean (SD))             1.094 (0.262)   0.257     
  TG_final (mean (SD))              1.816 (1.244)   0.534     
  systolic (mean (SD))            149.318 (24.602)  0.689     
  diastoli (mean (SD))             78.500 (14.500)  0.601     
  GFR_MDRD (mean (SD))             86.166 (36.012)  0.127     
  BMI (mean (SD))                  26.627 (3.794)   0.604     
  KDOQI (%)                          39.1           0.161     
                                     21.7                     
                                     26.1                     
                                     13.0                     
  BMI_WHO (%)                         4.3           0.730     
                                     26.1                     
                                     43.5                     
                                     17.4                     
                                      8.7                     
  SmokerStatus (%)                   26.1           0.972     
                                     56.5                     
                                     13.0                     
                                      4.3                     
  AlcoholUse (%)                     34.8           0.841     
                                     56.5                     
                                      8.7                     
  DiabetesStatus (%)                 60.9           0.145     
                                     39.1                     
  Hypertension.selfreport (%)        13.0           0.084     
                                     87.0                     
                                      0.0                     
  Hypertension.selfreportdrug (%)    13.0           0.319     
                                     82.6                     
                                      4.3                     
  Hypertension.composite (%)          8.7           1.000     
                                     91.3                     
  Hypertension.drugs (%)              8.7           0.889     
                                     87.0                     
                                      4.3                     
  Med.anticoagulants (%)             87.0           0.332     
                                      8.7                     
                                      4.3                     
  Med.all.antiplatelet (%)           21.7           0.947     
                                     73.9                     
                                      4.3                     
  Med.Statin.LLD (%)                 17.4           0.799     
                                     78.3                     
                                      4.3                     
  Stroke_Dx (%)                      56.5           1.000     
                                     43.5                     
  sympt (%)                          26.1           0.215     
                                      8.7                     
                                     26.1                     
                                      8.7                     
                                     17.4                     
                                      0.0                     
                                      0.0                     
                                      4.3                     
                                      8.7                     
  Symptoms.5G (%)                    26.1           0.126     
                                     26.1                     
                                      0.0                     
                                      4.3                     
                                     34.8                     
                                      8.7                     
  AsymptSympt (%)                    26.1           0.071     
                                     30.4                     
                                     43.5                     
  AsymptSympt2G (%)                  26.1           0.077     
                                     73.9                     
  Symptoms.Update2G (%)              26.1           0.077     
                                     73.9                     
  Symptoms.Update3G (%)              26.1           0.077     
                                     73.9                     
  indexsymptoms_latest_4g (%)        26.1           0.044     
                                     30.4                     
                                      8.7                     
                                     34.8                     
  restenos (%)                      100.0              NA     
  stenose (%)                         0.0           0.122     
                                     17.4                     
                                     34.8                     
                                     26.1                     
                                     21.7                     
  CAD_history (%)                    78.3           1.000     
                                     21.7                     
  PAOD (%)                           87.0           0.972     
                                     13.0                     
  Peripheral.interv (%)              78.3           1.000     
                                     21.7                     
  EP_composite (%)                   82.6           0.965     
                                     13.0                     
                                      4.3                     
  EP_composite_time (mean (SD))     2.330 (1.242)   0.226     
  EP_major (%)                       87.0           0.932     
                                      8.7                     
                                      4.3                     
  EP_major_time (mean (SD))         2.357 (1.254)   0.226     
  Macrophages.bin (%)                 4.3           1.000     
                                     95.7                     
  SMC.bin (%)                         4.3           1.000     
                                     95.7                     
  Calc.bin (%)                        4.3           1.000     
                                     95.7                     
  Collagen.bin (%)                    4.3           1.000     
                                     95.7                     
  Fat.bin_10 (%)                      4.3           1.000     
                                     95.7                     
  Fat.bin_40 (%)                      4.3           1.000     
                                     95.7                     
  OverallPlaquePhenotype (%)          4.3           1.000     
                                     95.7                     
  Plaque_Vulnerability_Index (%)     95.7           1.000     
                                      4.3                     

Baseline writing

Let’s save the baseline characteristics of the Athero-Express Biobank Study.

library(gtsummary)
library(dplyr)
library(haven)
# fix factor levels
scRNAseqDataMetaAE.all <- scRNAseqDataMetaAE.all %>%
  mutate(across(where(haven::is.labelled), haven::as_factor))
# Remove continuous variables with only one unique value (including NAs)
valid_vars <- scRNAseqDataMetaAE.all %>%
  gtsummary::select(all_of(basetable_vars)) %>%
  gtsummary::select(where(~n_distinct(., na.rm = TRUE) > 1)) %>%
  names()

# Rebuild the table with valid variables
# These warnings:
# `cannot compute exact p-value with ties`
# are non-fatal and expected when using non-parametric tests (e.g., Wilcoxon) on ranked or integer-valued data that may contain duplicates (ties)
# To control this manually:
# add_p(
#     test = all_continuous() ~ "t.test", # or "wilcox.test"
#     test.args = all_categorical() ~ list(simulate.p.value = TRUE)
#   )
# To have `gtsummary auto-select:
#   add_p()
scRNAseqDataMetaAE.all.tbl <- scRNAseqDataMetaAE.all %>%
  gtsummary::select(all_of(valid_vars), Gender) %>%
  tbl_summary(
    by = Gender,
    missing = "ifany",
    statistic = all_continuous() ~ "{mean} ({sd})"
  ) %>%
  add_p(
    test = all_continuous() ~ "t.test", # or "wilcox.test"
    test.args = all_categorical() ~ list(simulate.p.value = TRUE)
    ) %>%
  bold_labels()
library(writexl)

# Convert to a clean data frame
scRNAseqDataMetaAE.all.tbl_df <- scRNAseqDataMetaAE.all.tbl %>% as_tibble()

# Save to Excel
write.xlsx(scRNAseqDataMetaAE.all.tbl_df,
           file = paste0(BASELINE_loc, "/",Today,".",PROJECTNAME,".AESCRNA.CEA.39pts.after_qc.IC_academic.BaselineTable.xlsx"), 
           rowNames = FALSE, 
           colNames = TRUE, 
           sheetName = "AESCRNA_byGender", overwrite = TRUE)
library(officer)
library(flextable)

# Format for Word output with Calibri font and size 9
ft <- gtsummary::as_flex_table(scRNAseqDataMetaAE.all.tbl) %>%
  theme_vanilla() %>%
  autofit() %>%
  set_table_properties(layout = "autofit") %>%
  flextable::font(fontname = "Calibri", part = "all") %>%
  flextable::fontsize(size = 9, part = "all")

# Save to Word
doc <- read_docx() %>%
  body_add_par("Baseline characteristics Athero-Express SCRNA Study -- stratified by Gender") %>%
  body_add_flextable(ft)
print(doc, target = paste0(BASELINE_loc, "/",Today,".",PROJECTNAME,".AESCRNA.CEA.39pts.after_qc.IC_academic.BaselineTable.docx"))

# Print message
message("Table exported successfully to *.AESCRNA.CEA.39pts.after_qc.IC_academic.BaselineTable.xlsx and *.AESCRNA.CEA.39pts.after_qc.IC_academic.BaselineTable.docx with Calibri font and size 9.")
rm(ft, doc)

Subset scRNAseq data

List of samples to be included based on informed consent (see above).

samples_of_interest <- unlist(scRNAseqDataMetaAE.all$Patient)
samples_of_interest
 [1] "4440" "4447" "4443" "4450" "4453" "4470" "4459" "4458" "4455" "4487" "4472" "4480" "4477" "4448"
[15] "4486" "4488" "4502" "4500" "4501" "4530" "4541" "4542" "4513" "4535" "4546" "4545" "4571" "4489"
[29] "4491" "4495" "4496" "4521" "4520" "4580" "4602" "4605" "4601" "4676" "4653"

Just make sure to keep the rows (patientid.plateid.cellid) in the data, so we will create a new column for that.

scRNAseqData$cell.ident <- rownames(scRNAseqData[[]])

Subsetting the samples of interest based on samples_of_interest.

scRNAseqDataCEA39 <- subset(scRNAseqData, subset = Patient %in% samples_of_interest)

Re-running SCTransform()

Since we subsetted we need to re-run SCTransform().


# Extract the SCTModel
sct_model <- scRNAseqData@assays$SCT@SCTModel.list

# Inspect the regression variables
sct_model
$model1
An sctransform model.
  Model formula:  y ~ log_umi 
  Parameters stored for 16036 features, 4948 cells.
# Inspect the default assay
DefaultAssay(scRNAseqDataCEA39)
[1] "RNA"
scRNAseqDataCEA39 <- SCTransform(scRNAseqDataCEA39, verbose = TRUE)

  |                                                                                                   
  |                                                                                             |   0%
  |                                                                                                   
  |=======================                                                                      |  25%
  |                                                                                                   
  |==============================================                                               |  50%
  |                                                                                                   
  |======================================================================                       |  75%
  |                                                                                                   
  |=============================================================================================| 100%

Selecting the clinical data of interest.

variables_of_interest <- c("Hospital", "ORyear", "Artery_summary",
                           "Age", "Gender",
                           "TC_final", "LDL_final", "HDL_final", "TG_final",
                           "systolic", "diastoli", "GFR_MDRD", "BMI",
                           "KDOQI", "BMI_WHO",
                           "SmokerStatus", "AlcoholUse",
                           "DiabetesStatus",
                           "Hypertension.selfreport", "Hypertension.selfreportdrug", "Hypertension.composite", "Hypertension.drugs",
                           "Med.anticoagulants", "Med.all.antiplatelet", "Med.Statin.LLD",
                           "Stroke_Dx",
                           "sympt", "Symptoms.5G", "AsymptSympt", "AsymptSympt2G",
                           "Symptoms.Update2G", "Symptoms.Update3G", "indexsymptoms_latest_4g",
                           "restenos", "stenose",
                           "CAD_history", "PAOD", "Peripheral.interv",
                           "EP_composite", "EP_composite_time", "EP_major", "EP_major_time")

temp <- subset(scRNAseqDataMetaAE.all, select = c("Patient", variables_of_interest))

Now we are merging in the clinical data of interest.

# Step 1: Extract original metadata from Seurat object
original_metadata_df <- scRNAseqDataCEA39@meta.data

# Step 2: Merge with dataframe (temp) with select variables based on 'Patient' column
merged_metadata_df <- merge(original_metadata_df, temp, by = "Patient", all.x = TRUE, sort = FALSE)

# Step 3: Exclude already existing columns to avoid duplication
new_metadata_columns <- setdiff(colnames(temp), colnames(original_metadata_df))
new_meta_info_df <- merged_metadata_df[, new_metadata_columns, drop = FALSE]

# Step 4: Add the new metadata to the Seurat object
scRNAseqDataCEA39 <- AddMetaData(scRNAseqDataCEA39, metadata = new_meta_info_df)

# Step 5: Rename `Patient` to `STUDY_NUMBER` to match the clinical data
scRNAseqDataCEA39@meta.data <- dplyr::rename(scRNAseqDataCEA39@meta.data, "STUDY_NUMBER" = "Patient")

# Verify that the new metadata was added correctly
head(scRNAseqDataCEA39@meta.data)
NA

Saving new dataset

temp2 <- as_tibble(subset(scRNAseqDataCEA39@meta.data, select = c("STUDY_NUMBER", "orig.ident", "nCount_RNA", "nFeature_RNA",
                                                                 "Plate", "Batch", "C.H", "Type", "percent.mt",
                                                                 "nCount_SCT", "nFeature_SCT", "seurat_clusters")))

# fwrite(temp2,
#        file = paste0(OUT_loc, "/", Today, ".AESCRNA.CEA.39pts.samplelist.after_qc.IC_commercial.csv"),
#        sep = ",", row.names = FALSE, col.names = TRUE,
#        showProgress = TRUE)
# rm(temp2)
# 
# temp <- dplyr::rename(temp, "STUDY_NUMBER" = "Patient")
# fwrite(temp,
#        file = paste0(OUT_loc, "/", Today, ".AESCRNA.CEA.39pts.clinicaldata.after_qc.IC_commercial.csv"),
#        sep = ",", row.names = FALSE, col.names = TRUE,
#        showProgress = TRUE)
# rm(temp)
# 
# saveRDS(scRNAseqDataCEA39, file = paste0(OUT_loc, "/", Today, ".AESCRNA.CEA.39pts.Seurat.after_qc.IC_commercial.RDS"))

fwrite(temp2,
       file = paste0(OUT_loc, "/", Today, ".AESCRNA.CEA.39pts.samplelist.after_qc.IC_academic.csv"),
       sep = ",", row.names = FALSE, col.names = TRUE,
       showProgress = TRUE)
rm(temp2)

temp <- dplyr::rename(temp, "STUDY_NUMBER" = "Patient")
fwrite(temp,
       file = paste0(OUT_loc, "/", Today, ".AESCRNA.CEA.39pts.clinicaldata.after_qc.IC_academic.csv"),
       sep = ",", row.names = FALSE, col.names = TRUE,
       showProgress = TRUE)
rm(temp)

saveRDS(scRNAseqDataCEA39, file = paste0(OUT_loc, "/", Today, ".AESCRNA.CEA.39pts.Seurat.after_qc.IC_academic.RDS"))

AESCRNA

Quality control

Here review the number of cells per sample, plate, and patients. And plot the ratio’s per sample and study number.

## check stuff
cat("\nHow many cells per type ...?")

How many cells per type ...?
sort(table(scRNAseqDataCEA39@meta.data$SCT_snn_res.1.25))

 16  22  23  21  12  19  18  17  15   2  10  11   9  13   5   8   4   6   3   0   1 
  8  17  19  23  26  55  78  94 112 172 173 176 198 199 242 243 293 297 348 831 846 
# cat("\n\nHow many cells per plate ...?")
# sort(table(scRNAseqDataCEA39@meta.data$ID))

# cat("\n\nHow many cells per type per plate ...?")
# table(scRNAseqDataCEA39@meta.data$SCT_snn_res.0.8, scRNAseqDataCEA39@meta.data$ID)

cat("\n\nHow many cells per patient ...?")


How many cells per patient ...?
sort(table(scRNAseqDataCEA39@meta.data$STUDY_NUMBER))

4530 4440 4605 4653 4472 4458 4455 4496 4601 4502 4501 4571 4448 4477 4459 4520 4602 4489 4495 4545 
   3    6    7   20   22   35   54   70   70   73   75   76   80   84   94   96   96   97  102  106 
4480 4447 4500 4513 4535 4676 4486 4470 4487 4546 4488 4521 4580 4491 4541 4450 4542 4453 4443 
 112  114  116  123  130  135  137  144  144  144  146  161  163  175  178  205  213  222  422 
cat("\n\nVisualizing these ratio's per study number and sample ...?")


Visualizing these ratio's per study number and sample ...?
UMAPPlot(scRNAseqDataCEA39, label = TRUE, pt.size = 1.25, label.size = 4, group.by = "ident",
         repel = TRUE)
ggsave(paste0(PLOT_loc, "/", Today, ".UMAP.png"), plot = last_plot())
ggsave(paste0(PLOT_loc, "/", Today, ".UMAP.ps"), plot = last_plot())



# barplot(prop.table(x = table(scRNAseqDataCEA39@active.ident, scRNAseqDataCEA39@meta.data$Patient)), 
#         cex.axis = 1.0, cex.names = 0.5, las = 1,
#         col = uithof_color, xlab = "study number", legend.text = FALSE, args.legend = list(x = "bottom"))
# dev.copy(pdf, paste0(QC_loc, "/", Today, ".cell_ratios_per_sample.pdf"))
# dev.off()

# barplot(prop.table(x = table(scRNAseqDataCEA39@active.ident, scRNAseqDataCEA39@meta.data$ID)), 
#         cex.axis = 1.0, cex.names = 0.5, las = 2,
#         col = uithof_color, xlab = "sample ID", legend.text = FALSE, args.legend = list(x = "bottom"))
# dev.copy(pdf, paste0(QC_loc, "/", Today, ".cell_ratios_per_sample_per_plate.pdf"))
# dev.off()

Visualisations

Feature plots of known cellular markers

Let’s project known cellular markers.

UMAPPlot(scRNAseqDataCEA39, label = FALSE, pt.size = 1.25, label.size = 4, group.by = "ident",
         repel = TRUE)


# endothelial cells
FeaturePlot(scRNAseqDataCEA39, features = c("CD34"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("EDN1"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("EDNRA", "EDNRB"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("CDH5", "PECAM1"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("ACKR1"), cols =  c("#ECECEC", "#DB003F"))


# SMC
FeaturePlot(scRNAseqDataCEA39, features = c("MYH11"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("LGALS3", "ACTA2"), cols =  c("#ECECEC", "#DB003F"))


# macrophages
FeaturePlot(scRNAseqDataCEA39, features = c("CD14", "CD68"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("CD36"), cols =  c("#ECECEC", "#DB003F"))


# t-cells
FeaturePlot(scRNAseqDataCEA39, features = c("CD3E"), cols =  c("#ECECEC", "#DB003F"))

FeaturePlot(scRNAseqDataCEA39, features = c("CD4"), cols =  c("#ECECEC", "#DB003F"))

# FeaturePlot(scRNAseqDataCEA39, features = c("CD8"), cols =  c("#ECECEC", "#DB003F"))

# b-cells
FeaturePlot(scRNAseqDataCEA39, features = c("CD79A"), cols =  c("#ECECEC", "#DB003F"))


# mast cells
FeaturePlot(scRNAseqDataCEA39, features = c("KIT"), cols =  c("#ECECEC", "#DB003F"))


# NK cells
FeaturePlot(scRNAseqDataCEA39, features = c("NCAM1"), cols =  c("#ECECEC", "#DB003F"))

Targets of interest:

We check whether the targets genes were sequenced using our method. In case some genes are not available in our data we could filter them here.

target_genes <- gene_list
target_genes
 [1] "SCGB3A2"  "LIX1"     "IGSF9B"   "ND6"      "ALB"      "OR10A4"   "RASEF"    "NEDD4"    "TRIM49D1"
[10] "TCL1A"    "ND4L"     "ATP8"     "FBXO15"   "F5"       "TMEM212"  "PTPRD"    "CYP46A1"  "OR2T33"  
[19] "SORBS2"   "ITGA7"    "RNASE1"   "FOS"      "HMOX1"    "LAPTM5"   "MMP9"     "SIGLEC1"  "FTL"     
[28] "CD14"     "HCST"     "TIMP3"    "CCL2"     "SAT1"     "CD163"    "PTGDS"    "LGALS9"   "ACKR1"   
[37] "NT5DC2"   "TGFBI"    "C1QC"     "S100A9"  

This code is just an example to filter the list from genes that are not in the data.

  • ND6 ==> not found
  • TRIM49D1 ==> not found
  • ND4L ==> not found
  • ATP8 ==> not found
  • RNASE1 ==> not found

gene_list_rm <- c("ND6", "TRIM49D1",
                  "ND4L", "ATP8", "RNASE1") 

temp = target_genes[!target_genes %in% gene_list_rm]

target_genes_qc <- c(temp)

# gene_list_qc <- gene_list
# 
# for debug
# gene_list_qc_replace <- c("MRTFA")

# target_genes_qc <- target_genes
target_genes_qc
 [1] "SCGB3A2" "LIX1"    "IGSF9B"  "ALB"     "OR10A4"  "RASEF"   "NEDD4"   "TCL1A"   "FBXO15" 
[10] "F5"      "TMEM212" "PTPRD"   "CYP46A1" "OR2T33"  "SORBS2"  "ITGA7"   "FOS"     "HMOX1"  
[19] "LAPTM5"  "MMP9"    "SIGLEC1" "FTL"     "CD14"    "HCST"    "TIMP3"   "CCL2"    "SAT1"   
[28] "CD163"   "PTGDS"   "LGALS9"  "ACKR1"   "NT5DC2"  "TGFBI"   "C1QC"    "S100A9" 

Expression in cell communities

library(RColorBrewer)

p1 <- DotPlot(scRNAseqDataCEA39, 
              features = target_genes_qc,
              cols = "RdBu") + 
  theme(axis.text.x = element_text(angle = 45, hjust=1, size = 8)) +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank()) # remove the y- and x-axis labels

p1

ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.png"), plot = last_plot())
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ps"), plot = last_plot())
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.pdf"), plot = last_plot())


rm(p1)

Let’s group this dotplot based on some grouping.

If we want we can also filter the genes that are not found in the data.

# Assuming 'gene_list_df' is your data.frame with the relevant columns loaded
gene_list_df_filtered <- subset(gene_list_df, Comments != "not found" | is.na(Comments))
gene_list_df_filtered

Expression in cell communities grouped

# Separate genes by significance
gene_list_df_filtered_up <- gene_list_df_filtered$GeneSymbol[gene_list_df_filtered$significance == "UP"]
gene_list_df_filtered_down <- gene_list_df_filtered$GeneSymbol[gene_list_df_filtered$significance == "DOWN"]

# Combine the genes, first DOWN then UP (or vice versa based on preference)
ordered_genes_qc <- c(gene_list_df_filtered_up, gene_list_df_filtered_down)
library(RColorBrewer)
# Create DotPlot ordered
p1_group <- DotPlot(scRNAseqData, 
              features = ordered_genes_qc, 
              cols = "RdBu") + 
  theme(axis.text.x = element_text(angle = 45, hjust=1, size = 8)) +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank()) # remove the y- and x-axis labels

p1_group

# Save the plots
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.Grouped.png"), plot = p1_group)
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.Grouped.ps"), plot = p1_group)
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.Grouped.pdf"), plot = p1_group)

Plotting gender

We should also plot these data stratified by gender smooth muscle cells.

Create subsets
unique(scRNAseqDataCEA39$Gender)
[1] male   female
Levels: female male
# Subset Seurat object for Males
male_cells <- WhichCells(scRNAseqDataCEA39, expression = Gender == "male")
scRNAseqDataCEA39_males <- subset(scRNAseqDataCEA39, cells = male_cells)

# Subset Seurat object for Females
female_cells <- WhichCells(scRNAseqDataCEA39, expression = Gender == "female")
scRNAseqDataCEA39_females <- subset(scRNAseqDataCEA39, cells = female_cells)
Smooth muscle cells

Get an overview of the various cell communities.

unique(scRNAseqDataCEA39@active.ident)
 [1] CD3+ TC I                  CD3+ TC IV                 CD34+ EC I                
 [4] CD3+ TC V                  CD3+CD56+ NK II            CD3+ TC VI                
 [7] CD68+IL18+TLR4+TREM2+ MRes CD3+CD56+ NK I             ACTA2+ SMC                
[10] CD3+ TC II                 FOXP3+ TC                  CD34+ EC II               
[13] CD3+ TC III                CD68+CD1C+ DC              CD68+CASP1+IL1B+SELL MInf 
[16] CD79A+ BCmem               CD68+ABCA1+OLR1+TREM2+ FC  CD68+KIT+ MC              
[19] CD68+CD4+ Mono             CD79+ BCplasma            
20 Levels: CD68+CD4+ Mono CD68+IL18+TLR4+TREM2+ MRes CD68+CD1C+ DC ... CD79+ BCplasma

Select the cell community of interest - in this example ‘smooth muscle cells’ defined by ACTA2+ SMC.

# Define the cell identities you want to include in the plot
selected_idents_cells <- c("ACTA2+ SMC")
library(RColorBrewer)
library(cowplot)  # For combining plots

# Create DotPlot for males
p1_males_cells <- DotPlot(scRNAseqDataCEA39_males,
                       features = ordered_genes_qc,
                       idents = selected_idents_cells, 
                       
                       cols = "RdBu") + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 8)) +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank()) + 
  ggtitle("Males")

# Create DotPlot for females
p2_females_cells <- DotPlot(scRNAseqDataCEA39_females,
                           features = ordered_genes_qc,
                           idents = selected_idents_cells,
                           
                           cols = "RdBu") + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 8)) +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank()) + 
  # theme(axis.title.x = element_blank(),
  #       axis.title.y = element_blank(),
  #       axis.text.y = element_blank(),  # Remove y-axis text
  #       axis.ticks.y = element_blank()) +  # Remove y-axis ticks 
  ggtitle("Females")

# Combine the two plots into one panel using cowplot
combined_plot_cells <- plot_grid(p1_males_cells, p2_females_cells, ncol = 2)

# Display the combined plot
print(combined_plot_cells)


# Save the plots
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.GenderMales.png"), plot = p1_males_cells)
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.GenderMales.ps"), plot = p1_males_cells)
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.GenderMales.pdf"), plot = p1_males_cells)

ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.GenderFemales.png"), plot = p2_females_cells)
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.GenderFemales.ps"), plot = p2_females_cells)
ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.GenderFemales.pdf"), plot = p2_females_cells)


# ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.Gender.png"), plot = combined_plot_cells)
# ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.Gender.ps"), plot = combined_plot_cells)
# ggsave(paste0(PLOT_loc, "/", Today, ".DotPlot.Targets.ColocGrouped.TCellonly.Gender.pdf"), plot = combined_plot_cells)
FeaturePlot(scRNAseqDataCEA39, features = c(target_genes_qc),
            cols =  c("#ECECEC", "#DB003F", "#9A3480","#1290D9"),
            combine = TRUE)

ggsave(paste0(PLOT_loc, "/", Today, ".FeaturePlot.Targets.png"), plot = last_plot())
ggsave(paste0(PLOT_loc, "/", Today, ".FeaturePlot.Targets.ps"), plot = last_plot())

# VlnPlot(scRNAseqDataCEA39, features = "DUSP27")

# VlnPlot files
ifelse(!dir.exists(file.path(PLOT_loc, "/VlnPlot")), 
       dir.create(file.path(PLOT_loc, "/VlnPlot")), 
       FALSE)
[1] FALSE
VlnPlot_loc = paste0(PLOT_loc, "/VlnPlot")


for (GENE in target_genes_qc){
  print(paste0("Projecting the expression of ", GENE, "."))

  vp1 <-  VlnPlot(scRNAseqDataCEA39, features = GENE) + 
    xlab("cell communities") + 
    ylab(bquote("normalized expression")) +
    theme(axis.title.x = element_text(color = "#000000", size = 14, face = "bold"), 
            axis.title.y = element_text(color = "#000000", size = 14, face = "bold"), 
            legend.position = "none")
    ggsave(paste0(VlnPlot_loc, "/", Today, ".VlnPlot.",GENE,".png"), plot = last_plot())
    ggsave(paste0(VlnPlot_loc, "/", Today, ".VlnPlot.",GENE,".ps"), plot = last_plot())
    ggsave(paste0(VlnPlot_loc, "/", Today, ".VlnPlot.",GENE,".pdf"), plot = last_plot())
  
  # print(vp1)
  
}
[1] "Projecting the expression of SCGB3A2."
[1] "Projecting the expression of LIX1."
[1] "Projecting the expression of IGSF9B."
[1] "Projecting the expression of ALB."
[1] "Projecting the expression of OR10A4."
[1] "Projecting the expression of RASEF."
[1] "Projecting the expression of NEDD4."
[1] "Projecting the expression of TCL1A."
[1] "Projecting the expression of FBXO15."
[1] "Projecting the expression of F5."
[1] "Projecting the expression of TMEM212."
[1] "Projecting the expression of PTPRD."
[1] "Projecting the expression of CYP46A1."
[1] "Projecting the expression of OR2T33."
[1] "Projecting the expression of SORBS2."
[1] "Projecting the expression of ITGA7."
[1] "Projecting the expression of FOS."
[1] "Projecting the expression of HMOX1."
[1] "Projecting the expression of LAPTM5."
[1] "Projecting the expression of MMP9."
[1] "Projecting the expression of SIGLEC1."
[1] "Projecting the expression of FTL."
[1] "Projecting the expression of CD14."
[1] "Projecting the expression of HCST."
[1] "Projecting the expression of TIMP3."
[1] "Projecting the expression of CCL2."
[1] "Projecting the expression of SAT1."
[1] "Projecting the expression of CD163."
[1] "Projecting the expression of PTGDS."
[1] "Projecting the expression of LGALS9."
[1] "Projecting the expression of ACKR1."
[1] "Projecting the expression of NT5DC2."
[1] "Projecting the expression of TGFBI."
[1] "Projecting the expression of C1QC."
[1] "Projecting the expression of S100A9."

Differential expression between cell communities

Here we project genes to only the broad cell communities:

  • macrophages
  • endothelial cells
  • smooth muscle cells
  • T-cells
  • B-cells
  • Mast cells
  • NK-cells
  • Mixed cells

Macrophages

unique(scRNAseqDataCEA39@active.ident)
 [1] CD3+ TC I                  CD3+ TC IV                 CD34+ EC I                
 [4] CD3+ TC V                  CD3+CD56+ NK II            CD3+ TC VI                
 [7] CD68+IL18+TLR4+TREM2+ MRes CD3+CD56+ NK I             ACTA2+ SMC                
[10] CD3+ TC II                 FOXP3+ TC                  CD34+ EC II               
[13] CD3+ TC III                CD68+CD1C+ DC              CD68+CASP1+IL1B+SELL MInf 
[16] CD79A+ BCmem               CD68+ABCA1+OLR1+TREM2+ FC  CD68+KIT+ MC              
[19] CD68+CD4+ Mono             CD79+ BCplasma            
20 Levels: CD68+CD4+ Mono CD68+IL18+TLR4+TREM2+ MRes CD68+CD1C+ DC ... CD79+ BCplasma

Comparison between the macrophages cell communities (CD14/CD68+), and all other communities.


MAC.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC"), 
                          ident.2 = c(#"CD68+CASP1+IL1B+SELL MInf", 
                                      #"CD68+CD1C+ DC", 
                                      #"CD68+CD4+ Mono",
                                      #"CD68+IL18+TLR4+TREM2+ MRes",
                                      #"CD68+ABCA1+OLR1+TREM2+ FC",
                                      "CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC", 
                                      "CD34+ EC I", 
                                      "CD34+ EC II",
                                      "ACTA2+ SMC", 
                                      "CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II", 
                                      "CD68+KIT+ MC",
                                      "CD79+ BCplasma", 
                                      "CD79A+ BCmem"))

DT::datatable(MAC.markers)
MAC_Volcano_TargetsA = EnhancedVolcano(MAC.markers,
    lab = rownames(MAC.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "Macrophage markers\n(Macrophage communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/(nrow(MAC.markers)), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
MAC_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.MAC.DEG.Targets.pdf"), 
       plot = MAC_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
MAC.markers <- add_column(MAC.markers, Gene = row.names(MAC.markers), .before = 1)

temp <- MAC.markers[MAC.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".MAC.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

Smooth muscle cells

Comparison between the smooth muscle cell communities (ACTA2+), and all other communities.


SMC.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("ACTA2+ SMC"), 
                          ident.2 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC",
                                      "CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC", 
                                      "CD34+ EC I", 
                                      "CD34+ EC II",
                                      #"ACTA2+ SMC", 
                                      "CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II", 
                                      "CD68+KIT+ MC",
                                      "CD79+ BCplasma", 
                                      "CD79A+ BCmem"))

DT::datatable(SMC.markers)
SMC_Volcano_TargetsA = EnhancedVolcano(SMC.markers,
    lab = rownames(SMC.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "SMC markers\n(SMC communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/(nrow(SMC.markers)), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
SMC_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.SMC.DEG.Targets.pdf"), 
       plot = SMC_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
SMC.markers <- add_column(SMC.markers, Gene = row.names(SMC.markers), .before = 1)

temp <- SMC.markers[SMC.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".SMC.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

Endothelial cells

Comparison between the endothelial cell communities (CD34+), and all other communities.


EC.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("CD34+ EC I", 
                                      "CD34+ EC II"), 
                          ident.2 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC",
                                      "CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC", 
                                      # "CD34+ EC I", 
                                      # "CD34+ EC II",
                                      "ACTA2+ SMC", 
                                      "CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II", 
                                      "CD68+KIT+ MC",
                                      "CD79+ BCplasma", 
                                      "CD79A+ BCmem"))

DT::datatable(EC.markers)
EC_Volcano_TargetsA = EnhancedVolcano(EC.markers,
    lab = rownames(EC.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "Endothelial cell markers\n(EC communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/(nrow(EC.markers)), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
EC_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.EC.DEG.Targets.pdf"), 
       plot = EC_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
EC.markers <- add_column(EC.markers, Gene = row.names(EC.markers), .before = 1)

temp <- EC.markers[EC.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".EC.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

T-cells

Comparison between the T-cell communities (CD3/CD4/CD8+), and all other communities.


TC.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC"), 
                          ident.2 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC",
                                      # "CD3+ TC I",
                                      # "CD3+ TC II", 
                                      # "CD3+ TC III", 
                                      # "CD3+ TC IV", 
                                      # "CD3+ TC V", 
                                      # "CD3+ TC VI", 
                                      # "FOXP3+ TC", 
                                      "CD34+ EC I", 
                                      "CD34+ EC II",
                                      "ACTA2+ SMC", 
                                      "CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II", 
                                      "CD68+KIT+ MC",
                                      "CD79+ BCplasma", 
                                      "CD79A+ BCmem"))

DT::datatable(TC.markers)
TC_Volcano_TargetsA = EnhancedVolcano(TC.markers,
    lab = rownames(TC.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "T-cell markers\n(T-cell communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/nrow(TC.markers), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
TC_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.TC.DEG.Targets.pdf"), 
       plot = TC_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
TC.markers <- add_column(TC.markers, Gene = row.names(TC.markers), .before = 1)

temp <- TC.markers[TC.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".TC.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

B-cells

Comparison between the B-cell communities (CD79A+), and all other communities.


BC.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("CD79+ BCplasma", 
                                      "CD79A+ BCmem"), 
                          ident.2 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC",
                                      "CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC", 
                                      "CD34+ EC I", 
                                      "CD34+ EC II",
                                      "ACTA2+ SMC", 
                                      "CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II", 
                                      "CD68+KIT+ MC"
                                      # "CD79+ BCplasma", 
                                      # "CD79A+ BCmem"
                                      ))

DT::datatable(BC.markers)
BC_Volcano_TargetsA = EnhancedVolcano(BC.markers,
    lab = rownames(BC.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "B-cell markers\n(B-cell communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/nrow(BC.markers), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
BC_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.BC.DEG.Targets.pdf"), 
       plot = BC_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
BC.markers <- add_column(BC.markers, Gene = row.names(BC.markers), .before = 1)

temp <- BC.markers[BC.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".BC.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

Mast cells

Comparison between the mast cell communities (KIT+), and all other communities.


MC.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("CD68+KIT+ MC"), 
                          ident.2 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC",
                                      "CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC", 
                                      "CD34+ EC I", 
                                      "CD34+ EC II",
                                      "ACTA2+ SMC", 
                                      "CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II", 
                                      # "CD68+KIT+ MC",
                                      "CD79+ BCplasma", 
                                      "CD79A+ BCmem"))

DT::datatable(MC.markers)
MC_Volcano_TargetsA = EnhancedVolcano(MC.markers,
    lab = rownames(MC.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "Mast cell markers\n(Mast cell communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/nrow(MC.markers), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
MC_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.MC.DEG.Targets.pdf"), 
       plot = MC_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
MC.markers <- add_column(MC.markers, Gene = row.names(MC.markers), .before = 1)

temp <- MC.markers[MC.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".MC.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

NK-cells

Comparison between the natural killer cell communities (NCAM1+), and all other communities.


NK.markers <- FindMarkers(object = scRNAseqDataCEA39, 
                          ident.1 = c("CD3+CD56+ NK I",
                                      "CD3+CD56+ NK II"), 
                          ident.2 = c("CD68+CASP1+IL1B+SELL MInf", 
                                      "CD68+CD1C+ DC", 
                                      "CD68+CD4+ Mono",
                                      "CD68+IL18+TLR4+TREM2+ MRes",
                                      "CD68+ABCA1+OLR1+TREM2+ FC",
                                      "CD3+ TC I",
                                      "CD3+ TC II", 
                                      "CD3+ TC III", 
                                      "CD3+ TC IV", 
                                      "CD3+ TC V", 
                                      "CD3+ TC VI", 
                                      "FOXP3+ TC", 
                                      "CD34+ EC I", 
                                      "CD34+ EC II",
                                      "ACTA2+ SMC", 
                                      # "CD3+CD56+ NK I",
                                      # "CD3+CD56+ NK II", 
                                      "CD68+KIT+ MC",
                                      "CD79+ BCplasma", 
                                      "CD79A+ BCmem"))

DT::datatable(NK.markers)
NK_Volcano_TargetsA = EnhancedVolcano(NK.markers,
    lab = rownames(NK.markers),
    x = "avg_log2FC",
    y = "p_val_adj",
    selectLab = target_genes_qc,
    axisLabSize = 12,
    xlab = "average fold-change",
    title = "NK markers\n(NK-cell communities vs the rest)",
    titleLabSize = 14,
    pCutoff = 0.05/nrow(NK.markers), # 20552 genes
    FCcutoff = 1.25,
    pointSize = 1.5,
    labSize = 3.0,
    legendLabels =c('NS','avg. fold-change','P',
      'P & avg. fold-change'),
    legendPosition = "right",
    legendLabSize = 10,
    legendIconSize = 3.0,
    drawConnectors = TRUE,
    widthConnectors = 0.2,
    colConnectors = "#595A5C",
    gridlines.major = FALSE,
    gridlines.minor = FALSE)
NK_Volcano_TargetsA
ggsave(paste0(PLOT_loc, "/", Today, ".Volcano.NK.DEG.Targets.pdf"), 
       plot = NK_Volcano_TargetsA)

The target results are given below and written to a file.

library(tibble)
NK.markers <- add_column(NK.markers, Gene = row.names(NK.markers), .before = 1)

temp <- NK.markers[NK.markers$Gene %in% target_genes_qc,]

DT::datatable(temp)
fwrite(temp, file = paste0(OUT_loc, "/", Today, ".NK.DEG.Targets.txt"),
       quote = FALSE,
       sep = "\t", 
       showProgress = FALSE, verbose = FALSE)

Macrophage Top 50 Genes

Let’s get the subset of most differentially expression genes for each subtype of macrophage, and compare these to the other cell communities.

library(tibble)
library(data.table)  # for fwrite

# 1 - Define mapping of short prefixes to full cluster names:
cell_types <- c(
  MAC_MINF = "CD68+CASP1+IL1B+SELL MInf",
  MAC_DC   = "CD68+CD1C+ DC",
  MAC_MONO = "CD68+CD4+ Mono",
  MAC_MRES = "CD68+IL18+TLR4+TREM2+ MRes",
  MAC_FC   = "CD68+ABCA1+OLR1+TREM2+ FC"
)

# 2 - Pull out the full list of clusters (so we can set ident.2 = everything else)
all_clusters <- unname(cell_types)

# 3 - Loop over each cell_type:
for (prefix in names(cell_types)) {
  full_name <- cell_types[prefix]
  
  # define ident.2 as “all clusters except the one in ident.1”
  other_clusters <- setdiff(all_clusters, full_name)
  
  # 4 - Run FindMarkers
  markers <- FindMarkers(
    object  = scRNAseqDataCEA39,
    ident.1 = full_name,
    ident.2 = other_clusters
  )
  
  # 5 - add Gene column
  markers <- add_column(markers, Gene = rownames(markers), .before = 1)
  
  # 6 - Sort by p-value (most significant first)
  markers_sorted_all <- markers[order(markers$p_val), , drop = FALSE]
  top50_all         <- head(markers_sorted_all, 50)
  
  # 7 - Remove HLA- genes, then sort & take top 50
  noHLA             <- markers[!grepl("^HLA-", markers$Gene), , drop = FALSE]
  markers_sorted_noHLA <- noHLA[order(noHLA$p_val), , drop = FALSE]
  top50_noHLA       <- head(markers_sorted_noHLA, 50)
  
  # 8 - Write both files
  base_name <- paste0(Today, ".", prefix)
  fwrite(top50_all,    file = file.path(OUT_loc, paste0(base_name, ".Top50All.txt")),
         quote = FALSE, sep = "\t", showProgress = FALSE, verbose = FALSE)
  fwrite(top50_noHLA,  file = file.path(OUT_loc, paste0(base_name, ".Top50NoHLA.txt")),
         quote = FALSE, sep = "\t", showProgress = FALSE, verbose = FALSE)
  
  message("Wrote files for ", prefix, ":\n",
          "  • Top 50 (all genes):    ", base_name, ".Top50All.txt\n",
          "  • Top 50 (no HLA-genes): ", base_name, ".Top50NoHLA.txt")
}

Session information


Version:      v1.2.3
Last update:  2025-07-02
Written by:   Sander W. van der Laan (s.w.vanderlaan-2[at]umcutrecht.nl).
Description:  Script to load single-cell RNA sequencing (scRNAseq) data, and perform quality control (QC), and initial mapping to cells.
Minimum requirements: R version 3.5.2 (2018-12-20) -- 'Eggshell Igloo', macOS Mojave (10.14.2).

**MoSCoW To-Do List**
The things we Must, Should, Could, and Would have given the time we have.
_M_

_S_

_C_

_W_

**Changes log**
* v1.2.3 Added a loop to extract the top 50 markers for each macrophage subtype.
* v1.2.2 Update to the writing of the baseline characteristics and tables.
* v1.2.1 Some fixes to the subsetting of a cell community and the visualization by group of target genes. 
* v1.2.0 Fixed an issue where the subset of scRNAseq was loosing cell-identities.
* v1.1.1 Textual fixes.
* v1.1.1 Fix writing baseline table.
* v1.1.0 Update to study database.
* v1.0.2 Fixes to the start of the notebook. Update to loading of the clinical data. Fix on the gene-filtering.
* v1.0.1 Update to main AEDB (there is an error in the Age-variable in the new version). Fewer patients in scRNAseq (32 vs 39 with the newer dataset).
* v1.0.0 Initial version.

sessionInfo()
R version 4.5.1 (2025-06-13)
Platform: x86_64-apple-darwin20
Running under: macOS Sequoia 15.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: Europe/Amsterdam
tzcode source: internal

attached base packages:
[1] stats4    tools     stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] cowplot_1.1.3          RColorBrewer_1.1-3     flextable_0.9.7        officer_0.6.8         
 [5] writexl_1.5.4          gtsummary_2.2.0        labelled_2.14.1        openxlsx_4.2.8        
 [9] rmarkdown_2.29         worcs_0.1.18           Seurat_5.3.0           SeuratObject_5.1.0    
[13] sp_2.2-0               devtools_2.4.5         usethis_3.1.0          BiocManager_1.30.25   
[17] tableone_0.13.2        haven_2.5.4            EnhancedVolcano_1.26.0 ggrepel_0.9.6         
[21] mygene_1.44.0          txdbmaker_1.4.1        GenomicFeatures_1.60.0 GenomicRanges_1.60.0  
[25] GenomeInfoDb_1.44.0    org.Hs.eg.db_3.21.0    AnnotationDbi_1.70.0   IRanges_2.42.0        
[29] S4Vectors_0.46.0       Biobase_2.68.0         BiocGenerics_0.54.0    generics_0.1.4        
[33] DT_0.33                knitr_1.50             lubridate_1.9.4        forcats_1.0.0         
[37] stringr_1.5.1          purrr_1.0.4            tibble_3.3.0           ggplot2_3.5.2         
[41] tidyverse_2.0.0        data.table_1.17.2      naniar_1.1.0           tidylog_1.1.0         
[45] tidyr_1.3.1            dplyr_1.1.4            optparse_1.7.5         readr_2.1.5           

loaded via a namespace (and not attached):
  [1] progress_1.2.3              urlchecker_1.0.1            nnet_7.3-20                
  [4] goftest_1.2-3               katex_1.5.0                 Biostrings_2.76.0          
  [7] vctrs_0.6.5                 spatstat.random_3.4-1       rticles_0.27               
 [10] digest_0.6.37               png_0.1-8                   proxy_0.4-27               
 [13] deldir_2.0-4                parallelly_1.44.0           renv_1.1.4                 
 [16] fontLiberation_0.1.0        MASS_7.3-65                 reshape2_1.4.4             
 [19] httpuv_1.6.16               withr_3.0.2                 ggrastr_1.0.2              
 [22] xfun_0.52                   ellipsis_0.3.2              survival_3.8-3             
 [25] memoise_2.0.1               ggbeeswarm_0.7.2            profvis_0.4.0              
 [28] systemfonts_1.2.3           ragg_1.4.0                  zoo_1.8-14                 
 [31] V8_6.0.3                    pbapply_1.7-2               Formula_1.2-5              
 [34] sys_3.4.3                   prettyunits_1.2.0           KEGGREST_1.48.0            
 [37] promises_1.3.2              httr_1.4.7                  restfulr_0.0.15            
 [40] globals_0.18.0              fitdistrplus_1.2-2          rstudioapi_0.17.1          
 [43] UCSC.utils_1.4.0            miniUI_0.1.2                base64enc_0.1-3            
 [46] curl_6.2.2                  mitools_2.4                 polyclip_1.10-7            
 [49] GenomeInfoDbData_1.2.14     SparseArray_1.8.0           xtable_1.8-4               
 [52] evaluate_1.0.3              S4Arrays_1.8.0              BiocFileCache_2.16.0       
 [55] hms_1.1.3                   irlba_2.3.5.1               colorspace_2.1-1           
 [58] filelock_1.0.3              getopt_1.20.4               ROCR_1.0-11                
 [61] reticulate_1.42.0           spatstat.data_3.1-6         magrittr_2.0.3             
 [64] lmtest_0.9-40               glmGamPoi_1.20.0            later_1.4.2                
 [67] lattice_0.22-7              spatstat.geom_3.4-1         future.apply_1.11.3        
 [70] scattermore_1.2             XML_3.99-0.18               survey_4.4-2               
 [73] matrixStats_1.5.0           RcppAnnoy_0.0.22            class_7.3-23               
 [76] Hmisc_5.2-3                 pillar_1.10.2               nlme_3.1-168               
 [79] beachmat_2.24.0             compiler_4.5.1              RSpectra_0.16-2            
 [82] stringi_1.8.7               tensor_1.5                  SummarizedExperiment_1.38.1
 [85] GenomicAlignments_1.44.0    plyr_1.8.9                  crayon_1.5.3               
 [88] abind_1.4-8                 BiocIO_1.18.0               chron_2.3-62               
 [91] bit_4.6.0                   codetools_0.2-20            textshaping_1.0.1          
 [94] clisymbols_1.2.0            openssl_2.3.2               crosstalk_1.2.1            
 [97] bslib_0.9.0                 e1071_1.7-16                plotly_4.10.4              
[100] mime_0.13                   splines_4.5.1               Rcpp_1.0.14                
[103] fastDummies_1.7.5           sparseMatrixStats_1.20.0    dbplyr_2.5.0               
[106] blob_1.2.4                  fs_1.6.6                    listenv_0.9.1              
[109] checkmate_2.3.2             DelayedMatrixStats_1.30.0   prereg_0.6.0               
[112] pkgbuild_1.4.7              gh_1.4.1                    sqldf_0.4-11               
[115] Matrix_1.7-3                statmod_1.5.0               tzdb_0.5.0                 
[118] visdat_0.6.0                equatags_0.2.1              pkgconfig_2.0.3            
[121] cachem_1.1.0                RSQLite_2.3.11              viridisLite_0.4.2          
[124] DBI_1.2.3                   fastmap_1.2.0               scales_1.4.0               
[127] grid_4.5.1                  gt_1.0.0                    credentials_2.0.2          
[130] ica_1.0-3                   cards_0.6.0                 Rsamtools_2.24.0           
[133] sass_0.4.10                 broom_1.0.8                 patchwork_1.3.1.9000       
[136] cardx_0.2.4                 dotCall64_1.2               RANN_2.6.2                 
[139] rpart_4.1.24                farver_2.1.2                gsubfn_0.7                 
[142] yaml_2.3.10                 MatrixGenerics_1.20.0       foreign_0.8-90             
[145] rtracklayer_1.68.0          cli_3.6.5                   lifecycle_1.0.4            
[148] askpass_1.2.1               uwot_0.2.3                  presto_1.0.0               
[151] sessioninfo_1.2.3           backports_1.5.0             BiocParallel_1.42.0        
[154] timechange_0.3.0            gtable_0.3.6                rjson_0.2.23               
[157] ggridges_0.5.6              progressr_0.15.1            limma_3.64.1               
[160] parallel_4.5.1              jsonlite_2.0.0              RcppHNSW_0.6.0             
[163] bitops_1.0-9                bit64_4.6.0-1               Rtsne_0.17                 
[166] spatstat.utils_3.1-4        proto_1.0.0                 zip_2.3.3                  
[169] ranger_0.17.0               jquerylib_0.1.4             spatstat.univar_3.1-3      
[172] lazyeval_0.2.2              shiny_1.10.0                xslt_1.5.1                 
[175] htmltools_0.5.8.1           sctransform_0.4.2           rappdirs_0.3.3             
[178] tinytex_0.57                glue_1.8.0                  spam_2.11-1                
[181] httr2_1.1.2                 XVector_0.48.0              gdtools_0.4.2              
[184] RCurl_1.98-1.17             gridExtra_2.3               igraph_2.1.4               
[187] R6_2.6.1                    labeling_0.4.3              cluster_2.1.8.1            
[190] pkgload_1.4.0               vipor_0.4.7                 DelayedArray_0.34.1        
[193] tidyselect_1.2.1            htmlTable_2.4.3             xml2_1.3.8                 
[196] fontBitstreamVera_0.1.1     future_1.49.0               KernSmooth_2.23-26         
[199] fontquiver_0.2.1            htmlwidgets_1.6.4           biomaRt_2.64.0             
[202] rlang_1.1.6                 spatstat.sparse_3.1-0       gert_2.1.5                 
[205] spatstat.explore_3.4-2      uuid_1.2-1                  remotes_2.5.0              
[208] beeswarm_0.4.0             

Saving environment

rm(backup.scRNAseqData)
rm(scRNAseqData, scRNAseqDataCEA39_females, scRNAseqDataCEA39_males)
# rm(scRNAseqDataCEA39) # Optional

save.image(paste0(PROJECT_loc, "/",Today,".",PROJECTNAME,".AESCRNA.results.RData"))
© 1979-2025 Sander W. van der Laan | s.w.vanderlaan[at]gmail[dot]com | vanderlaanand.science.
LS0tCnRpdGxlOiAiTWFwcGluZyB0YXJnZXRzIHRvIHNpbmdsZSBjZWxscyBpbiBwbGFxdWVzLiIKc3VidGl0bGU6IEFjY29tcGFueWluZyAnUEhFTk9NSUNMX2Rvd25zdHJlYW0nCmF1dGhvcjogJ1tTYW5kZXIgVy4gdmFuIGRlciBMYWFuLCBQaERdKGh0dHBzOi8vdmFuZGVybGFhbmFuZC5zY2llbmNlKSB8IHMudy52YW5kZXJsYWFuW2F0XWdtYWlsW2RvdF1jb20nCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IAogICAgY2FjaGU6IHllcwogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2xsYXBzZTogeWVzCiAgICBkZl9wcmludDogcGFnZWQKICAgIGZpZy5hbGlnbjogY2VudGVyCiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBmaWdfaGVpZ2h0OiAxMAogICAgZmlnX3JldGluYTogMgogICAgZmlnX3dpZHRoOiAxMgogICAgdGhlbWU6IHBhcGVyCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IG5vCiAgICAgIHNtb290aF9zY3JvbGw6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwptYWluZm9udDogSGVsdmV0aWNhCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgprbml0OiB3b3Jjczo6Y2l0ZV9hbGwKLS0tCgojIEdlbmVyYWwgU2V0dXAKYGBge3IgZWNobyA9IEZBTFNFfQpybShsaXN0ID0gbHMoKSkKYGBgCgpgYGB7ciBMb2NhbFN5c3RlbSwgZWNobyA9IEZBTFNFfQpzb3VyY2UoInNjcmlwdHMvbG9jYWwuc3lzdGVtLlIiKQpgYGAKCmBgYHtyIFNvdXJjZSBmdW5jdGlvbnN9CnNvdXJjZSgic2NyaXB0cy9mdW5jdGlvbnMuUiIpCmBgYAoKYGBge3IgbG9hZGluZ19wYWNrYWdlcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc291cmNlKCJzY3JpcHRzL3BhY2swMy5wYWNrYWdlcy5SIikKYGBgCgpgYGB7ciBTZXR0aW5nOiBDb2xvcnN9ClRvZGF5ID0gZm9ybWF0KGFzLkRhdGUoYXMuUE9TSVhsdChTeXMudGltZSgpKSksICIlWSVtJWQiKQpUb2RheS5SZXBvcnQgPSBmb3JtYXQoYXMuRGF0ZShhcy5QT1NJWGx0KFN5cy50aW1lKCkpKSwgIiVBLCAlQiAlZCwgJVkiKQpzb3VyY2UoInNjcmlwdHMvY29sb3JzLlIiKQpgYGAKCmBgYHtyIHNldHVwX25vdGVib29rLCBpbmNsdWRlPUZBTFNFfQojIFdlIHJlY29tbWVuZCB0aGF0IHlvdSBwcmVwYXJlIHlvdXIgcmF3IGRhdGEgZm9yIGFuYWx5c2lzIGluICdwcmVwYXJlX2RhdGEuUicsCiMgYW5kIGVuZCB0aGF0IGZpbGUgd2l0aCBlaXRoZXIgb3Blbl9kYXRhKHlvdXJkYXRhKSwgb3IgY2xvc2VkX2RhdGEoeW91cmRhdGEpLgojIFRoZW4sIHVuY29tbWVudCB0aGUgbGluZSBiZWxvdyB0byBsb2FkIHRoZSBvcmlnaW5hbCBvciBzeW50aGV0aWMgZGF0YQojICh3aGljaGV2ZXIgaXMgYXZhaWxhYmxlKSwgdG8gYWxsb3cgYW55b25lIHRvIHJlcHJvZHVjZSB5b3VyIGNvZGU6CiMgbG9hZF9kYXRhKCkKCiMgZnVydGhlciBkZWZpbmUgc29tZSBrbml0ci1vcHRpb25zLgprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA4LCBmaWcucGF0aCA9ICdGaWd1cmVzLycsIAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IFRSVUUsICMgc2hvdyB3YXJuaW5ncyBkdXJpbmcgY29kZWJvb2sgZ2VuZXJhdGlvbgogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IFRSVUUsICMgc2hvdyBtZXNzYWdlcyBkdXJpbmcgY29kZWJvb2sgZ2VuZXJhdGlvbgogICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBUUlVFLCAjIGRvIG5vdCBpbnRlcnJ1cHQgY29kZWJvb2sgZ2VuZXJhdGlvbiBpbiBjYXNlIG9mIGVycm9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdXN1YWxseSBiZXR0ZXIgZm9yIGRlYnVnZ2luZwogICAgICAgICAgICAgICAgICAgICAgZWNobyA9IFRSVUUsICAjIHNob3cgUiBjb2RlCiAgICAgICAgICAgICAgICAgICAgICBldmFsID0gVFJVRSkKCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9taW5pbWFsKCkpCiMgcGFuZGVyOjpwYW5kZXJPcHRpb25zKCJ0YWJsZS5zcGxpdC50YWJsZSIsIEluZikKbGlicmFyeSgid29yY3MiKQpsaWJyYXJ5KCJybWFya2Rvd24iKQoKYGBgCgojIEVSQS1DVkQgJ2RydWdnYWJsZS1NSS10YXJnZXRzJwoKPCEtLSAhW0VSQS1DVkQgbG9nb10oIlVzZXJzL3N3dmFuZGVybGFhbi9pQ2xvdWQvR2Vub21pY3MvUHJvamVjdHMvI0RydWdnYWJsZS1NSS1HZW5lcy9BZG1pbmlzdHJhdGlvbi9FUkEtQ1ZEXCBMb2dvX0NNWUsuanBnIikgLS0+CgpGb3IgdGhlIEVSQS1DVkQgJ2RydWdnYWJsZS1NSS10YXJnZXRzJyBwcm9qZWN0IChncmFudG51bWJlcjogMDFLTDE4MDIpIHdlIHBlcmZvcm1lZCB0d28gcmVsYXRlZCBSTkEgc2VxdWVuY2luZyAoUk5Bc2VxKSBleHBlcmltZW50czoKCjEpICBjb252ZW50aW9uYWwgKCdidWxrJykgUk5Bc2VxIHVzaW5nIFJOQSBleHRyYWN0ZWQgZnJvbSBjYXJvdGlkIHBsYXF1ZSBzYW1wbGVzLCBuIMKxIDcwMC4gQXMgb2YgYHIgVG9kYXkuUmVwb3J0YCBhbGwgc2FtcGxlcyBoYXZlIGJlZW4gc2VsZWN0ZWQgYW5kClJOQSBoYXMgYmVlbiBleHRyYWN0ZWQ7IHF1YWxpdHkgY29udHJvbCAoUUMpIHdhcyBwZXJmb3JtZWQgYW5kIHdlIGhhdmUgYSBkYXRhc2V0IG9mIDYzNSBzYW1wbGVzLgoKMikgIHNpbmdsZS1jZWxsIFJOQXNlcSAoc2NSTkFzZXEpIG9mIGF0IGxlYXN0IG4gPSA0MCBzYW1wbGVzICgyMCBmZW1hbGVzLCAyMCBtYWxlcykuIEFzIG9mIGByIFRvZGF5LlJlcG9ydGAgZGF0YSBpcyBhdmFpbGFibGUgb2YgNDAgc2FtcGxlcyAoMyBmZW1hbGVzLCAxNSBtYWxlcyksIHdlIGFyZSBleHRlbmRpbmcgc2FtcGxpbmcgdG8gZ2V0IG1vcmUgZmVtYWxlIHNhbXBsZXMuCgpQbGFxdWUgc2FtcGxlcyBhcmUgZGVyaXZlZCBmcm9tIGNhcm90aWQgZW5kYXJ0ZXJlY3RvbWllcyBhcyBwYXJ0IG9mIHRoZSBbQXRoZXJvLUV4cHJlc3MgQmlvYmFuayBTdHVkeV0oaHR0cDp3d3cvYXRoZXJvZXhwcmVzcy5ubCkgd2hpY2ggaXMgYW4gb25nb2luZyBzdHVkeSBpbiB0aGUgVU1DIFV0cmVjaHQuCgojIEJhY2tncm91bmQKCkhlcmUgd2UgbWFwIHRoZSBgciBUUkFJVF9PRl9JTlRFUkVTVGAgdG8gc2luZ2xlLWNlbGxzIGZyb20gdGhlIHBsYXF1ZXMuCgojIyBUYXJnZXRzCgpIZXJlIHdlIG9idGFpbiBkYXRhIGZyb20gdGhlIGByIFRSQUlUX09GX0lOVEVSRVNUYCBpbiBwbGFxdWVzLgoKYGBge3IgdGFyZ2V0cywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShvcGVueGxzeCkKCmdlbmVfbGlzdF9kZiA8LSByZWFkLnhsc3gocGFzdGUwKFBST0pFQ1RfbG9jLCAiL3RhcmdldHMvdGFyZ2V0cy54bHN4IiksIHNoZWV0ID0gIkdlbmVzIikKCmdlbmVfbGlzdCA8LSB1bmxpc3QoZ2VuZV9saXN0X2RmJEdlbmUpCmdlbmVfbGlzdAoKYGBgCgoKIyBMb2FkIGRhdGEKCkZpcnN0IHdlIHdpbGwgbG9hZCB0aGUgZGF0YToKCi0gICBzY1JOQXNlcSBleHBlcmltZW50YWwgZGF0YSBhbmQgcmVuYW1lIHRoZSBjZWxsIHR5cGVzLgotICAgQXRoZXJvLUV4cHJlc3MgY2xpbmljYWwgZGF0YS4KCkhlcmUgd2UgbG9hZCB0aGUgbGF0ZXN0IGRhdGFzZXQgZnJvbSBvdXIgQXRoZXJvLUV4cHJlc3Mgc2luZ2xlLWNlbGwgUk5BIGV4cGVyaW1lbnQuCgpgYGB7ciBMb2FkRGF0YX0KCiMgbG9hZChwYXN0ZTAoQUVTQ1JOQV9sb2MsICIvMjAyMTA4MTEuNDYucGF0aWVudHMuS1AuUkRhdGEiKSkKIyBzY1JOQXNlcURhdGEgPC0gc2V1c2V0CiMgcm0oc2V1c2V0KQojIAojIHNhdmVSRFMoc2NSTkFzZXFEYXRhLCBwYXN0ZTAoQUVTQ1JOQV9sb2MsICIvMjAyMTA4MTEuNDYucGF0aWVudHMuS1AuUkRTIikpCgpzY1JOQXNlcURhdGEgPC0gcmVhZFJEUyhwYXN0ZTAoQUVTQ1JOQV9sb2MsICIvMjAyMTA4MTEuNDYucGF0aWVudHMuS1AuUkRTIikpCgpzY1JOQXNlcURhdGEKCmBgYAoKVGhlIG5hbWluZy9jbGFzc2lmaWNhdGlvbiBpcyBiYXNlZCBvbiBhIGNvbWJpbmF0aW9uIGNvbnZlbnRpb25hbCBtYXJrZXJzLiBXZSBkbyBub3QgY2xhaW0gdG8ga25vdyB0aGUgZXhhY3QgaWRlbnRpdHkgb2YgZWFjaCBjZWxsLCByYXRoZXIgd2UgcmVmZXIgdG8gY2VsbHMgYXMgJ0tJVCsgTWFzdCBjZWxscyItbGlrZSBjZWxscy4gTGlrZXdpc2Ugd2UgcmVmZXIgdG8gdGhlIGNlbGwgY2x1c3RlcnMgYXMgJ2NvbW11bml0aWVzJyBvZiBjZWxscyB0aGF0IGV4aGliaXQgc2ltaWxhciBwcm9wZXJ0aWVzLCAqaS5lLiogc2ltaWxhciBkZWZpbmluZyBtYXJrZXJzICgqZS5nLiBLSVQqKS4KCldlIHdpbGwgcmVuYW1lIHRoZSBjZWxsIHR5cGVzIHRvIGh1bWFuIHJlYWRhYmxlIG5hbWVzLgoKYGBge3IgQ2hhbmdlIGNlbGwgY3VtbXVuaXR5IG5hbWVzfQojIyMgY2hhbmdlIG5hbWVzIGZvciBjbGFyaXR5CmJhY2t1cC5zY1JOQXNlcURhdGEgPSBzY1JOQXNlcURhdGEKIyBnZXQgdGhlIG9sZCBuYW1lcyB0byBjaGFuZ2UgdG8gbmV3IG5hbWVzClVNQVBQbG90KHNjUk5Bc2VxRGF0YSwgbGFiZWwgPSBGQUxTRSwgcHQuc2l6ZSA9IDEuMjUsIGxhYmVsLnNpemUgPSA0LCBncm91cC5ieSA9ICJpZGVudCIpCgpgYGAKCmBgYHtyfQp1bmlxdWUoc2NSTkFzZXFEYXRhQGFjdGl2ZS5pZGVudCkKYGBgCgpgYGB7cn0KY2VsbHR5cGVzIDwtIGMoIkNENjgrQ0Q0KyBNb25vY3l0ZXMiID0gIkNENjgrQ0Q0KyBNb25vIiwgCiAgICAgICAgICAgICAgICJDRDY4K0lMMTgrVExSNCtUUkVNMisgUmVzaWRlbnQgbWFjcm9waGFnZXMiID0gIkNENjgrSUwxOCtUTFI0K1RSRU0yKyBNUmVzIiwgCiAgICAgICAgICAgICAgICJDRDY4K0NEMUMrIERlbmRyaXRpYyBDZWxscyIgPSAiQ0Q2OCtDRDFDKyBEQyIsCiAgICAgICAgICAgICAgICJDRDY4K0NBU1AxK0lMMUIrU0VMTCsgSW5mbGFtbWF0b3J5IG1hY3JvcGhhZ2VzIiA9ICJDRDY4K0NBU1AxK0lMMUIrU0VMTCBNSW5mIiwKICAgICAgICAgICAgICAgIkNENjgrQUJDQTErT0xSMStUUkVNMisgRm9hbSBDZWxscyIgPSAiQ0Q2OCtBQkNBMStPTFIxK1RSRU0yKyBGQyIsCiAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAjIFQtY2VsbHMKICAgICAgICAgICAgICAgIkNEMysgVCBDZWxscyBJIiA9ICJDRDMrIFRDIEkiLAogICAgICAgICAgICAgICAiQ0QzKyBUIENlbGxzIElJIiA9ICJDRDMrIFRDIElJIiwgCiAgICAgICAgICAgICAgICJDRDMrIFQgQ2VsbHMgSUlJIiA9ICJDRDMrIFRDIElJSSIsIAogICAgICAgICAgICAgICAiQ0QzKyBUIENlbGxzIElWIiA9ICJDRDMrIFRDIElWIiwgCiAgICAgICAgICAgICAgICJDRDMrIFQgQ2VsbHMgViIgPSAiQ0QzKyBUQyBWIiwgCiAgICAgICAgICAgICAgICJDRDMrIFQgQ2VsbHMgVkkiID0gIkNEMysgVEMgVkkiLCAKICAgICAgICAgICAgICAgIkZPWFAzKyBUIENlbGxzIiA9ICJGT1hQMysgVEMiLAogICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIyBFbmRvdGhlbGlhbCBjZWxscwogICAgICAgICAgICAgICAiQ0QzNCsgRW5kb3RoZWxpYWwgQ2VsbHMgSSIgPSAiQ0QzNCsgRUMgSSIsIAogICAgICAgICAgICAgICAiQ0QzNCsgRW5kb3RoZWxpYWwgQ2VsbHMgSUkiID0gIkNEMzQrIEVDIElJIiwgCiAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAjIFNNQwogICAgICAgICAgICAgICAiQUNUQTIrIFNtb290aCBNdXNjbGUgQ2VsbHMiID0gIkFDVEEyKyBTTUMiLCAKICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICMgTksgQ2VsbHMKICAgICAgICAgICAgICAgIkNEMytDRDU2KyBOSyBDZWxscyBJIiA9ICJDRDMrQ0Q1NisgTksgSSIsCiAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgQ2VsbHMgSUkiID0gIkNEMytDRDU2KyBOSyBJSSIsCiAgICAgICAgICAgICAgICMgTWFzdAogICAgICAgICAgICAgICAiQ0Q2OCtLSVQrIE1hc3QgQ2VsbHMiID0gIkNENjgrS0lUKyBNQyIsCiAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAiQ0Q3OUErIENsYXNzLXN3aXRjaGVkIE1lbW9yeSBCIENlbGxzIiA9ICJDRDc5QSsgQkNtZW0iLCAKICAgICAgICAgICAgICAgIkNENzkrIFBsYXNtYSBCIENlbGxzIiA9ICJDRDc5KyBCQ3BsYXNtYSIpCgpzY1JOQXNlcURhdGEgPC0gU2V1cmF0OjpSZW5hbWVJZGVudHMob2JqZWN0ID0gc2NSTkFzZXFEYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbHR5cGVzKQpgYGAKCmBgYHtyIENoYW5nZSBjZWxsIGN1bW11bml0eSBuYW1lcyAtIG5ldyBwbG90fQpVTUFQUGxvdChzY1JOQXNlcURhdGEsIGxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDEuMjUsIGxhYmVsLnNpemUgPSA0LCBncm91cC5ieSA9ICJpZGVudCIsCiAgICAgICAgIHJlcGVsID0gVFJVRSkKCmBgYAoKIyMgQ2xpbmljYWwgZGF0YQoKTG9hZGluZyB0aGUgQXRoZXJvLUV4cHJlc3MgY2xpbmljYWwgZGF0YS4KCmBgYHtyIExvYWRBRURCfQojIEFFREIuQ0VBIDwtIHJlYWRSRFMoZmlsZSA9IHBhc3RlMChPVVRfbG9jLCAiLyIsIFRvZGF5LCIuIixQUk9KRUNUTkFNRSwiLkFFREIuQ0VBLlJEUyIpKQpBRURCLkNFQSA8LSByZWFkUkRTKGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8yMDI0MTIxOS4iLFBST0pFQ1ROQU1FLCIuQUVEQi5DRUEuUkRTIikpCgpgYGAKCgpgYGB7ciB9CiMgQmFzZWxpbmUgdGFibGUgdmFyaWFibGVzCmJhc2V0YWJsZV92YXJzID0gYygiSG9zcGl0YWwiLCAiT1J5ZWFyIiwgIkFydGVyeV9zdW1tYXJ5IiwKICAgICAgICAgICAgICAgICAgICJBZ2UiLCAiR2VuZGVyIiwgCiAgICAgICAgICAgICAgICAgICAjICJUQ19maW5hbENVIiwgIkxETF9maW5hbENVIiwgIkhETF9maW5hbENVIiwgIlRHX2ZpbmFsQ1UiLCAKICAgICAgICAgICAgICAgICAgICJUQ19maW5hbCIsICJMRExfZmluYWwiLCAiSERMX2ZpbmFsIiwgIlRHX2ZpbmFsIiwgCiAgICAgICAgICAgICAgICAgICAjICJoc0NSUF9wbGFzbWEiLAogICAgICAgICAgICAgICAgICAgInN5c3RvbGljIiwgImRpYXN0b2xpIiwgIkdGUl9NRFJEIiwgIkJNSSIsIAogICAgICAgICAgICAgICAgICAgIktET1FJIiwgIkJNSV9XSE8iLAogICAgICAgICAgICAgICAgICAgIlNtb2tlclN0YXR1cyIsICJBbGNvaG9sVXNlIiwKICAgICAgICAgICAgICAgICAgICJEaWFiZXRlc1N0YXR1cyIsIAogICAgICAgICAgICAgICAgICAgIkh5cGVydGVuc2lvbi5zZWxmcmVwb3J0IiwgIkh5cGVydGVuc2lvbi5zZWxmcmVwb3J0ZHJ1ZyIsICJIeXBlcnRlbnNpb24uY29tcG9zaXRlIiwgIkh5cGVydGVuc2lvbi5kcnVncyIsIAogICAgICAgICAgICAgICAgICAgIk1lZC5hbnRpY29hZ3VsYW50cyIsICJNZWQuYWxsLmFudGlwbGF0ZWxldCIsICJNZWQuU3RhdGluLkxMRCIsIAogICAgICAgICAgICAgICAgICAgIlN0cm9rZV9EeCIsICJzeW1wdCIsICJTeW1wdG9tcy41RyIsICJBc3ltcHRTeW1wdCIsICJBc3ltcHRTeW1wdDJHIiwKICAgICAgICAgICAgICAgICAgICJTeW1wdG9tcy5VcGRhdGUyRyIsICJTeW1wdG9tcy5VcGRhdGUzRyIsICJpbmRleHN5bXB0b21zX2xhdGVzdF80ZyIsCiAgICAgICAgICAgICAgICAgICAicmVzdGVub3MiLCAic3Rlbm9zZSIsIAogICAgICAgICAgICAgICAgICAgIkNBRF9oaXN0b3J5IiwgIlBBT0QiLCAiUGVyaXBoZXJhbC5pbnRlcnYiLCAKICAgICAgICAgICAgICAgICAgICJFUF9jb21wb3NpdGUiLCAiRVBfY29tcG9zaXRlX3RpbWUiLCAiRVBfbWFqb3IiLCAiRVBfbWFqb3JfdGltZSIsCiAgICAgICAgICAgICAgICAgICAiTUFDX3JhbmtOb3JtIiwgIlNNQ19yYW5rTm9ybSIsICJNYWNyb3BoYWdlcy5iaW4iLCAiU01DLmJpbiIsCiAgICAgICAgICAgICAgICAgICAiTmV1dHJvcGhpbHNfcmFua05vcm0iLCAiTWFzdENlbGxzX3JhbmtOb3JtIiwKICAgICAgICAgICAgICAgICAgICJJUEguYmluIiwgIlZlc3NlbERlbnNpdHlfcmFua05vcm0iLAogICAgICAgICAgICAgICAgICAgIkNhbGMuYmluIiwgIkNvbGxhZ2VuLmJpbiIsIAogICAgICAgICAgICAgICAgICAgIkZhdC5iaW5fMTAiLCAiRmF0LmJpbl80MCIsICJPdmVyYWxsUGxhcXVlUGhlbm90eXBlIiwgIlBsYXF1ZV9WdWxuZXJhYmlsaXR5X0luZGV4IiwKICAgICAgICAgICAgICAgICAgICJQQ1NLOV9wbGFzbWEiLCAiUENTSzlfcGxhc21hX3JhbmtOb3JtIikKCmJhc2V0YWJsZV9iaW4gPSBjKCJHZW5kZXIiLCAgIkFydGVyeV9zdW1tYXJ5IiwKICAgICAgICAgICAgICAgICAgIktET1FJIiwgIkJNSV9XSE8iLAogICAgICAgICAgICAgICAgICAiU21va2VyU3RhdHVzIiwgIkFsY29ob2xVc2UiLAogICAgICAgICAgICAgICAgICAiRGlhYmV0ZXNTdGF0dXMiLCAKICAgICAgICAgICAgICAgICAgIkh5cGVydGVuc2lvbi5zZWxmcmVwb3J0IiwgIkh5cGVydGVuc2lvbi5zZWxmcmVwb3J0ZHJ1ZyIsICJIeXBlcnRlbnNpb24uY29tcG9zaXRlIiwgIkh5cGVydGVuc2lvbi5kcnVncyIsIAogICAgICAgICAgICAgICAgICAiTWVkLmFudGljb2FndWxhbnRzIiwgIk1lZC5hbGwuYW50aXBsYXRlbGV0IiwgIk1lZC5TdGF0aW4uTExEIiwgCiAgICAgICAgICAgICAgICAgICJTdHJva2VfRHgiLCAic3ltcHQiLCAiU3ltcHRvbXMuNUciLCAiQXN5bXB0U3ltcHQiLCAiQXN5bXB0U3ltcHQyRyIsCiAgICAgICAgICAgICAgICAgICJTeW1wdG9tcy5VcGRhdGUyRyIsICJTeW1wdG9tcy5VcGRhdGUzRyIsICJpbmRleHN5bXB0b21zX2xhdGVzdF80ZyIsCiAgICAgICAgICAgICAgICAgICJyZXN0ZW5vcyIsICJzdGVub3NlIiwKICAgICAgICAgICAgICAgICAgIkNBRF9oaXN0b3J5IiwgIlBBT0QiLCAiUGVyaXBoZXJhbC5pbnRlcnYiLCAKICAgICAgICAgICAgICAgICAgIkVQX21ham9yIiwgIkVQX2NvbXBvc2l0ZSIsICJNYWNyb3BoYWdlcy5iaW4iLCAiU01DLmJpbiIsCiAgICAgICAgICAgICAgICAgICJJUEguYmluIiwgCiAgICAgICAgICAgICAgICAgICJDYWxjLmJpbiIsICJDb2xsYWdlbi5iaW4iLCAKICAgICAgICAgICAgICAgICAgIkZhdC5iaW5fMTAiLCAiRmF0LmJpbl80MCIsICJPdmVyYWxsUGxhcXVlUGhlbm90eXBlIiwgIlBsYXF1ZV9WdWxuZXJhYmlsaXR5X0luZGV4IikKIyBiYXNldGFibGVfYmluCgpiYXNldGFibGVfY29uID0gYmFzZXRhYmxlX3ZhcnNbIWJhc2V0YWJsZV92YXJzICVpbiUgYmFzZXRhYmxlX2Jpbl0KIyBiYXNldGFibGVfY29uCmBgYAoKIyMgQUVTQ1JOQTogYmFzZWxpbmUgY2hhcmFjdGVyaXN0aWNzCgojIyMgUHJlcGFyYXRpb24KCmBgYHtyIEJhc2VsaW5lOiBjcmVhdGlvbn0KbWV0YWRhdGEgPC0gc2NSTkFzZXFEYXRhQG1ldGEuZGF0YSAlPiUgYXNfdGliYmxlKCkgJT4lIHNlcGFyYXRlKG9yaWcuaWRlbnQsIGMoIlBhdGllbnQiLCBOQSkpCnNjUk5Bc2VxRGF0YU1ldGEgPC0gbWV0YWRhdGEgJT4lIGRpc3RpbmN0KFBhdGllbnQsIC5rZWVwX2FsbCA9IFRSVUUpCgpzY1JOQXNlcURhdGFNZXRhQUUgPC0gbWVyZ2Uoc2NSTkFzZXFEYXRhTWV0YSwgQUVEQi5DRUEsIGJ5LnggPSAiUGF0aWVudCIsIGJ5LnkgPSAiU1RVRFlfTlVNQkVSIiwgc29ydCA9IEZBTFNFLCBhbGwueCA9IFRSVUUpCmRpbShzY1JOQXNlcURhdGFNZXRhQUUpCgojIFJlcGxhY2UgbWlzc2luZyBkYXRhIAojIFJlZjogaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL25hbmlhci92aWduZXR0ZXMvcmVwbGFjZS13aXRoLW5hLmh0bWwKcmVxdWlyZShuYW5pYXIpCgpuYV9zdHJpbmdzIDwtIGMoIk5BIiwgIk4gQSIsICJOIC8gQSIsICJOL0EiLCAiTi8gQSIsIAogICAgICAgICAgICAgICAgIk5vdCBBdmFpbGFibGUiLCAiTm90IGF2YWlsYWJsZSIsIAogICAgICAgICAgICAgICAgIm1pc3NpbmciLCAKICAgICAgICAgICAgICAgICItOTk5IiwgIi05OSIsIAogICAgICAgICAgICAgICAgIk5vIGRhdGEgYXZhaWxhYmxlL21pc3NpbmciLCAiTm8gZGF0YSBhdmFpbGFibGUvTWlzc2luZyIpCiMgVGhlbiB5b3Ugd3JpdGUgfi54ICVpbiUgbmFfc3RyaW5ncyAtIHdoaWNoIHJlYWRzIGFzIOKAnGRvZXMgdGhpcyB2YWx1ZSBvY2N1ciBpbiB0aGUgbGlzdCBvZiBOQSBzdHJpbmdz4oCdLgoKc2NSTkFzZXFEYXRhTWV0YUFFICU+JQogIHJlcGxhY2Vfd2l0aF9uYV9hbGwoY29uZGl0aW9uID0gfi54ICVpbiUgbmFfc3RyaW5ncykKYGBgCgpgYGB7ciB9CmNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSIpCmNhdCgiU0VMRUNUSU9OIFRIRSBTSElaWkxFIikKCmNhdCgiLSBzYW5pdHkgY2hlY2tpbmcgUFJJT1IgdG8gc2VsZWN0aW9uIikKbGlicmFyeShkYXRhLnRhYmxlKQpyZXF1aXJlKGxhYmVsbGVkKQphZS5nZW5kZXIgPC0gdG9fZmFjdG9yKHNjUk5Bc2VxRGF0YU1ldGFBRSRHZW5kZXIpCmFlLmhvc3BpdGFsIDwtIHRvX2ZhY3RvcihzY1JOQXNlcURhdGFNZXRhQUUkSG9zcGl0YWwpCnRhYmxlKGFlLmdlbmRlciwgYWUuaG9zcGl0YWwsIGRubiA9IGMoIlNleCIsICJIb3NwaXRhbCIpLCB1c2VOQSA9ICJpZmFueSIpCgphZS5hcnRlcnkgPC0gdG9fZmFjdG9yKHNjUk5Bc2VxRGF0YU1ldGFBRSRBcnRlcnlfc3VtbWFyeSkKdGFibGUoYWUuYXJ0ZXJ5LCBhZS5nZW5kZXIsIGRubiA9IGMoIlNleCIsICJBcnRlcnkiKSwgdXNlTkEgPSAiaWZhbnkiKQoKYWUuaWMgPC0gdG9fZmFjdG9yKHNjUk5Bc2VxRGF0YU1ldGFBRSRpbmZvcm1lZGNvbnNlbnQpCnRhYmxlKGFlLmljLCBhZS5nZW5kZXIsIHVzZU5BID0gImlmYW55IikKCnJtKGFlLmdlbmRlciwgYWUuaG9zcGl0YWwsIGFlLmFydGVyeSwgYWUuaWMpCgoKc2NSTkFzZXFEYXRhTWV0YUFFLmFsbCA8LSBzdWJzZXQoc2NSTkFzZXFEYXRhTWV0YUFFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoQXJ0ZXJ5X3N1bW1hcnkgPT0gImNhcm90aWQgKGxlZnQgJiByaWdodCkiIHwgQXJ0ZXJ5X3N1bW1hcnkgPT0gIm90aGVyIGNhcm90aWQgYXJ0ZXJpZXMgKGNvbW1vbiwgZXh0ZXJuYWwpIiApICYgIyB3ZSBvbmx5IHdhbnQgY2Fyb3RpZHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gIm1pc3NpbmciICYgIyB3ZSBhcmUgcmVhbGx5IHN0cmljdCBpbiBzZWxlY3RpbmcgYmFzZWQgb24gJ2luZm9ybWVkIGNvbnNlbnQnIQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAibm8sIGRpZWQiICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gdGlzc3VlLCBubyBjb21tZXJpY2FsIGJ1c2luZXNzIiAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIHRpc3N1ZSwgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIG1lZGljYWwgaW5mbywgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyB0aXNzdWUsIG5vIHF1ZXN0aW9ubmFpcmVzLCBubyBoZWFsdGggdHJlYXRtZW50LCBubyBjb21tZXJpY2FsIGJ1c2luZXNzIiAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIHRpc3N1ZSwgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIGhlYWx0aCB0cmVhdG1lbnQsIG5vIG1lZGljYWwgaW5mbywgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyB0aXNzdWUsIG5vIGhlYWx0aCB0cmVhdG1lbnQiICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gdGlzc3VlLCBubyBxdWVzdGlvbm5haXJlcyIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyB0aXNzdWUsIGhlYWx0aCB0cmVhdG1lbnQgd2hlbiBwb3NzaWJsZSIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyB0aXNzdWUiICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gdGlzc3VlLCBubyBxdWVzdGlvbm5haXJlcywgbm8gaGVhbHRoIHRyZWF0bWVudCwgbm8gbWVkaWNhbCBpbmZvIiAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIHRpc3N1ZSwgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIGhlYWx0aCB0cmVhdG1lbnQsIG5vIGNvbW1lcmNpYWwgYnVzaW5lc3MiICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gIm5vLCBkb2Vzbid0IHdhbnQgdG8iICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gIm5vLCB1bmFibGUgdG8gc2lnbiIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAibm8sIG5vIHJlYWN0aW9uIiAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJubywgbG9zdCIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAibm8sIHRvbyBvbGQiICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gbWVkaWNhbCBpbmZvLCBoZWFsdGggdHJlYXRtZW50IHdoZW4gcG9zc2libGUiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJubyAobmV2ZXIgYXNrZWQgZm9yIElDIGJlY2F1c2UgdGhlcmUgd2FzIG5vIHRpc3N1ZSkiICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gIm5vLCBlbmRwb2ludCIgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAibm9vaXQgZ2VpbmNsdWRlZXJkIiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyBoZWFsdGggdHJlYXRtZW50LCBubyBjb21tZXJjaWFsIGJ1c2luZXNzIiAmICMgSU1QT1JUQU5UOiBzaW5jZSB3ZSBhcmUgc2hhcmluZyB3aXRoIGEgY29tbWVyY2lhbCBwYXJ0eQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyB0aXNzdWUsIG5vIGNvbW1lcmljYWwgYnVzaW5lc3MiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIHRpc3N1ZSwgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIG1lZGljYWwgaW5mbywgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIGhlYWx0aCB0cmVhdG1lbnQsIG5vIGNvbW1lcmNpYWwgYnVzaW5lc3MiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIHRpc3N1ZSwgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIGhlYWx0aCB0cmVhdG1lbnQsIG5vIGNvbW1lcmljYWwgYnVzaW5lc3MiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIGhlYWx0aCB0cmVhdG1lbnQsIG5vIG1lZGljYWwgaW5mbywgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gdGlzc3VlLCBubyBxdWVzdGlvbm5haXJlcywgbm8gaGVhbHRoIHRyZWF0bWVudCwgbm8gbWVkaWNhbCBpbmZvLCBubyBjb21tZXJjaWFsIGJ1c2luZXNzIiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBubyBjb21tZXJpY2FsIGJ1c2luZXNzIiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWVkY29uc2VudCAhPSAieWVzLCBoZWFsdGggdHJlYXRtZW50IHdoZW4gcG9zc2libGUsIG5vIGNvbW1lcmNpYWwgYnVzaW5lc3MiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIG1lZGljYWwgaW5mbywgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gdGlzc3VlLCBubyBxdWVzdGlvbm5haXJlcywgbm8gaGVhbHRoIHRyZWF0bWVudCwgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1lZGNvbnNlbnQgIT0gInllcywgbm8gcXVlc3Rpb25uYWlyZXMsIG5vIGNvbW1lcmNpYWwgYnVzaW5lc3MiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJ5ZXMsIG5vIHF1ZXN0aW9ubmFpcmVzLCBoZWFsdGggdHJlYXRtZW50IHdoZW4gcG9zc2libGUsIG5vIGNvbW1lcmNpYWwgYnVzaW5lc3MiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtZWRjb25zZW50ICE9ICJzZWNvbmQgaW5mb3JtZWQgY29uY2VudHM6IHllcywgbm8gY29tbWVyY2lhbCBidXNpbmVzcyIpCiMgc2NSTkFzZXFEYXRhTWV0YUFFLmFsbFsxOjEwLCAxOjEwXQpkaW0oc2NSTkFzZXFEYXRhTWV0YUFFLmFsbCkKIyBEVDo6ZGF0YXRhYmxlKHNjUk5Bc2VxRGF0YU1ldGFBRS5hbGwpCgpgYGAKCiMjIyBCYXNlbGluZSBBRVNDUk5BIFN0dWR5CgpTaG93aW5nIHRoZSBiYXNlbGluZSB0YWJsZSBmb3IgdGhlIHNjUk5Bc2VxIGRhdGEgaW4gMzkgQ0VBIHBhdGllbnRzIHdpdGgKaW5mb3JtZWQgY29uc2VudC4KCmBgYHtyIEJhc2VsaW5lOiBWaXN1YWxpemV9CmNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSIpCmNhdCgiQ1JFQVRFIEJBU0VMSU5FIFRBQkxFIikKCiMgQ3JlYXRlIGJhc2VsaW5lIHRhYmxlcwojIGh0dHA6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMTMzMjFfZGEzMTQ2MzNkYjkyNGRjNzg5ODZhODUwODEzYTUwZDUuaHRtbApzY1JOQXNlcURhdGFNZXRhQUUuYWxsLnRhYmxlT25lID0gcHJpbnQoQ3JlYXRlVGFibGVPbmUodmFycyA9IGJhc2V0YWJsZV92YXJzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JWYXJzID0gYmFzZXRhYmxlX2JpbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJhdGEgPSAiR2VuZGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gc2NSTkFzZXFEYXRhTWV0YUFFLmFsbCwgaW5jbHVkZU5BID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbm5vcm1hbCA9IGMoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVvdGUgPSBGQUxTRSwgc2hvd0FsbExldmVscyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0ID0gInAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250RGlnaXRzID0gMykKCmBgYAoKCgojIyMgQmFzZWxpbmUgd3JpdGluZwoKTGV0J3Mgc2F2ZSB0aGUgYmFzZWxpbmUgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBBdGhlcm8tRXhwcmVzcyBCaW9iYW5rIFN0dWR5LgoKYGBge3IgQmFzZWxpbmUgU2FtcGxlU2VsZWN0aW9uOiB3cml0ZSBQcmVwYXJlIGZpeH0KbGlicmFyeShndHN1bW1hcnkpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoaGF2ZW4pCiMgZml4IGZhY3RvciBsZXZlbHMKc2NSTkFzZXFEYXRhTWV0YUFFLmFsbCA8LSBzY1JOQXNlcURhdGFNZXRhQUUuYWxsICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaGF2ZW46OmlzLmxhYmVsbGVkKSwgaGF2ZW46OmFzX2ZhY3RvcikpCmBgYAoKCmBgYHtyIEJhc2VsaW5lIFNhbXBsZVNlbGVjdGlvbjogd3JpdGUgUHJlcGFyZX0KIyBSZW1vdmUgY29udGludW91cyB2YXJpYWJsZXMgd2l0aCBvbmx5IG9uZSB1bmlxdWUgdmFsdWUgKGluY2x1ZGluZyBOQXMpCnZhbGlkX3ZhcnMgPC0gc2NSTkFzZXFEYXRhTWV0YUFFLmFsbCAlPiUKICBndHN1bW1hcnk6OnNlbGVjdChhbGxfb2YoYmFzZXRhYmxlX3ZhcnMpKSAlPiUKICBndHN1bW1hcnk6OnNlbGVjdCh3aGVyZSh+bl9kaXN0aW5jdCguLCBuYS5ybSA9IFRSVUUpID4gMSkpICU+JQogIG5hbWVzKCkKCiMgUmVidWlsZCB0aGUgdGFibGUgd2l0aCB2YWxpZCB2YXJpYWJsZXMKIyBUaGVzZSB3YXJuaW5nczoKIyBgY2Fubm90IGNvbXB1dGUgZXhhY3QgcC12YWx1ZSB3aXRoIHRpZXNgCiMgYXJlIG5vbi1mYXRhbCBhbmQgZXhwZWN0ZWQgd2hlbiB1c2luZyBub24tcGFyYW1ldHJpYyB0ZXN0cyAoZS5nLiwgV2lsY294b24pIG9uIHJhbmtlZCBvciBpbnRlZ2VyLXZhbHVlZCBkYXRhIHRoYXQgbWF5IGNvbnRhaW4gZHVwbGljYXRlcyAodGllcykKIyBUbyBjb250cm9sIHRoaXMgbWFudWFsbHk6CiMgYWRkX3AoCiMgICAgIHRlc3QgPSBhbGxfY29udGludW91cygpIH4gInQudGVzdCIsICMgb3IgIndpbGNveC50ZXN0IgojICAgICB0ZXN0LmFyZ3MgPSBhbGxfY2F0ZWdvcmljYWwoKSB+IGxpc3Qoc2ltdWxhdGUucC52YWx1ZSA9IFRSVUUpCiMgICApCiMgVG8gaGF2ZSBgZ3RzdW1tYXJ5IGF1dG8tc2VsZWN0OgojICAgYWRkX3AoKQpzY1JOQXNlcURhdGFNZXRhQUUuYWxsLnRibCA8LSBzY1JOQXNlcURhdGFNZXRhQUUuYWxsICU+JQogIGd0c3VtbWFyeTo6c2VsZWN0KGFsbF9vZih2YWxpZF92YXJzKSwgR2VuZGVyKSAlPiUKICB0Ymxfc3VtbWFyeSgKICAgIGJ5ID0gR2VuZGVyLAogICAgbWlzc2luZyA9ICJpZmFueSIsCiAgICBzdGF0aXN0aWMgPSBhbGxfY29udGludW91cygpIH4gInttZWFufSAoe3NkfSkiCiAgKSAlPiUKICBhZGRfcCgKICAgIHRlc3QgPSBhbGxfY29udGludW91cygpIH4gInQudGVzdCIsICMgb3IgIndpbGNveC50ZXN0IgogICAgdGVzdC5hcmdzID0gYWxsX2NhdGVnb3JpY2FsKCkgfiBsaXN0KHNpbXVsYXRlLnAudmFsdWUgPSBUUlVFKQogICAgKSAlPiUKICBib2xkX2xhYmVscygpCgpgYGAKCmBgYHtyIEJhc2VsaW5lIFNhbXBsZVNlbGVjdGlvbjogd3JpdGUgRXhjZWx9CmxpYnJhcnkod3JpdGV4bCkKCiMgQ29udmVydCB0byBhIGNsZWFuIGRhdGEgZnJhbWUKc2NSTkFzZXFEYXRhTWV0YUFFLmFsbC50YmxfZGYgPC0gc2NSTkFzZXFEYXRhTWV0YUFFLmFsbC50YmwgJT4lIGFzX3RpYmJsZSgpCgojIFNhdmUgdG8gRXhjZWwKd3JpdGUueGxzeChzY1JOQXNlcURhdGFNZXRhQUUuYWxsLnRibF9kZiwKICAgICAgICAgICBmaWxlID0gcGFzdGUwKEJBU0VMSU5FX2xvYywgIi8iLFRvZGF5LCIuIixQUk9KRUNUTkFNRSwiLkFFU0NSTkEuQ0VBLjM5cHRzLmFmdGVyX3FjLklDX2FjYWRlbWljLkJhc2VsaW5lVGFibGUueGxzeCIpLCAKICAgICAgICAgICByb3dOYW1lcyA9IEZBTFNFLCAKICAgICAgICAgICBjb2xOYW1lcyA9IFRSVUUsIAogICAgICAgICAgIHNoZWV0TmFtZSA9ICJBRVNDUk5BX2J5R2VuZGVyIiwgb3ZlcndyaXRlID0gVFJVRSkKCmBgYAoKCmBgYHtyIEJhc2VsaW5lIFNhbXBsZVNlbGVjdGlvbjogd3JpdGUgV29yZH0KbGlicmFyeShvZmZpY2VyKQpsaWJyYXJ5KGZsZXh0YWJsZSkKCiMgRm9ybWF0IGZvciBXb3JkIG91dHB1dCB3aXRoIENhbGlicmkgZm9udCBhbmQgc2l6ZSA5CmZ0IDwtIGd0c3VtbWFyeTo6YXNfZmxleF90YWJsZShzY1JOQXNlcURhdGFNZXRhQUUuYWxsLnRibCkgJT4lCiAgdGhlbWVfdmFuaWxsYSgpICU+JQogIGF1dG9maXQoKSAlPiUKICBzZXRfdGFibGVfcHJvcGVydGllcyhsYXlvdXQgPSAiYXV0b2ZpdCIpICU+JQogIGZsZXh0YWJsZTo6Zm9udChmb250bmFtZSA9ICJDYWxpYnJpIiwgcGFydCA9ICJhbGwiKSAlPiUKICBmbGV4dGFibGU6OmZvbnRzaXplKHNpemUgPSA5LCBwYXJ0ID0gImFsbCIpCgojIFNhdmUgdG8gV29yZApkb2MgPC0gcmVhZF9kb2N4KCkgJT4lCiAgYm9keV9hZGRfcGFyKCJCYXNlbGluZSBjaGFyYWN0ZXJpc3RpY3MgQXRoZXJvLUV4cHJlc3MgU0NSTkEgU3R1ZHkgLS0gc3RyYXRpZmllZCBieSBHZW5kZXIiKSAlPiUKICBib2R5X2FkZF9mbGV4dGFibGUoZnQpCnByaW50KGRvYywgdGFyZ2V0ID0gcGFzdGUwKEJBU0VMSU5FX2xvYywgIi8iLFRvZGF5LCIuIixQUk9KRUNUTkFNRSwiLkFFU0NSTkEuQ0VBLjM5cHRzLmFmdGVyX3FjLklDX2FjYWRlbWljLkJhc2VsaW5lVGFibGUuZG9jeCIpKQoKIyBQcmludCBtZXNzYWdlCm1lc3NhZ2UoIlRhYmxlIGV4cG9ydGVkIHN1Y2Nlc3NmdWxseSB0byAqLkFFU0NSTkEuQ0VBLjM5cHRzLmFmdGVyX3FjLklDX2FjYWRlbWljLkJhc2VsaW5lVGFibGUueGxzeCBhbmQgKi5BRVNDUk5BLkNFQS4zOXB0cy5hZnRlcl9xYy5JQ19hY2FkZW1pYy5CYXNlbGluZVRhYmxlLmRvY3ggd2l0aCBDYWxpYnJpIGZvbnQgYW5kIHNpemUgOS4iKQpybShmdCwgZG9jKQoKYGBgCgoKIyBTdWJzZXQgc2NSTkFzZXEgZGF0YQoKTGlzdCBvZiBzYW1wbGVzIHRvIGJlIGluY2x1ZGVkIGJhc2VkIG9uIGluZm9ybWVkIGNvbnNlbnQgKHNlZSBhYm92ZSkuCgpgYGB7cn0Kc2FtcGxlc19vZl9pbnRlcmVzdCA8LSB1bmxpc3Qoc2NSTkFzZXFEYXRhTWV0YUFFLmFsbCRQYXRpZW50KQpzYW1wbGVzX29mX2ludGVyZXN0CmBgYAoKSnVzdCBtYWtlIHN1cmUgdG8ga2VlcCB0aGUgcm93cyAoYHBhdGllbnRpZGAuYHBsYXRlaWRgLmBjZWxsaWRgKSBpbiB0aGUgZGF0YSwgc28gd2Ugd2lsbCBjcmVhdGUgYSBuZXcgY29sdW1uIGZvciB0aGF0LgoKYGBge3J9CnNjUk5Bc2VxRGF0YSRjZWxsLmlkZW50IDwtIHJvd25hbWVzKHNjUk5Bc2VxRGF0YVtbXV0pCmBgYAoKU3Vic2V0dGluZyB0aGUgc2FtcGxlcyBvZiBpbnRlcmVzdCBiYXNlZCBvbiBgc2FtcGxlc19vZl9pbnRlcmVzdGAuCgpgYGB7cn0Kc2NSTkFzZXFEYXRhQ0VBMzkgPC0gc3Vic2V0KHNjUk5Bc2VxRGF0YSwgc3Vic2V0ID0gUGF0aWVudCAlaW4lIHNhbXBsZXNfb2ZfaW50ZXJlc3QpCmBgYAoKIyMgUmUtcnVubmluZyBgU0NUcmFuc2Zvcm0oKWAKClNpbmNlIHdlIHN1YnNldHRlZCB3ZSBuZWVkIHRvIHJlLXJ1biBgU0NUcmFuc2Zvcm0oKWAuCgpgYGB7cn0KCiMgRXh0cmFjdCB0aGUgU0NUTW9kZWwKc2N0X21vZGVsIDwtIHNjUk5Bc2VxRGF0YUBhc3NheXMkU0NUQFNDVE1vZGVsLmxpc3QKCiMgSW5zcGVjdCB0aGUgcmVncmVzc2lvbiB2YXJpYWJsZXMKc2N0X21vZGVsCgojIEluc3BlY3QgdGhlIGRlZmF1bHQgYXNzYXkKRGVmYXVsdEFzc2F5KHNjUk5Bc2VxRGF0YUNFQTM5KQpgYGAKCmBgYHtyfQpzY1JOQXNlcURhdGFDRUEzOSA8LSBTQ1RyYW5zZm9ybShzY1JOQXNlcURhdGFDRUEzOSwgdmVyYm9zZSA9IFRSVUUpCmBgYAoKU2VsZWN0aW5nIHRoZSBjbGluaWNhbCBkYXRhIG9mIGludGVyZXN0LgoKYGBge3J9CnZhcmlhYmxlc19vZl9pbnRlcmVzdCA8LSBjKCJIb3NwaXRhbCIsICJPUnllYXIiLCAiQXJ0ZXJ5X3N1bW1hcnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQWdlIiwgIkdlbmRlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJUQ19maW5hbCIsICJMRExfZmluYWwiLCAiSERMX2ZpbmFsIiwgIlRHX2ZpbmFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgInN5c3RvbGljIiwgImRpYXN0b2xpIiwgIkdGUl9NRFJEIiwgIkJNSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJLRE9RSSIsICJCTUlfV0hPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNtb2tlclN0YXR1cyIsICJBbGNvaG9sVXNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRpYWJldGVzU3RhdHVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkh5cGVydGVuc2lvbi5zZWxmcmVwb3J0IiwgIkh5cGVydGVuc2lvbi5zZWxmcmVwb3J0ZHJ1ZyIsICJIeXBlcnRlbnNpb24uY29tcG9zaXRlIiwgIkh5cGVydGVuc2lvbi5kcnVncyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWQuYW50aWNvYWd1bGFudHMiLCAiTWVkLmFsbC5hbnRpcGxhdGVsZXQiLCAiTWVkLlN0YXRpbi5MTEQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU3Ryb2tlX0R4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgInN5bXB0IiwgIlN5bXB0b21zLjVHIiwgIkFzeW1wdFN5bXB0IiwgIkFzeW1wdFN5bXB0MkciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU3ltcHRvbXMuVXBkYXRlMkciLCAiU3ltcHRvbXMuVXBkYXRlM0ciLCAiaW5kZXhzeW1wdG9tc19sYXRlc3RfNGciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAicmVzdGVub3MiLCAic3Rlbm9zZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQURfaGlzdG9yeSIsICJQQU9EIiwgIlBlcmlwaGVyYWwuaW50ZXJ2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkVQX2NvbXBvc2l0ZSIsICJFUF9jb21wb3NpdGVfdGltZSIsICJFUF9tYWpvciIsICJFUF9tYWpvcl90aW1lIikKCnRlbXAgPC0gc3Vic2V0KHNjUk5Bc2VxRGF0YU1ldGFBRS5hbGwsIHNlbGVjdCA9IGMoIlBhdGllbnQiLCB2YXJpYWJsZXNfb2ZfaW50ZXJlc3QpKQpgYGAKCk5vdyB3ZSBhcmUgbWVyZ2luZyBpbiB0aGUgY2xpbmljYWwgZGF0YSBvZiBpbnRlcmVzdC4KCmBgYHtyfQojIFN0ZXAgMTogRXh0cmFjdCBvcmlnaW5hbCBtZXRhZGF0YSBmcm9tIFNldXJhdCBvYmplY3QKb3JpZ2luYWxfbWV0YWRhdGFfZGYgPC0gc2NSTkFzZXFEYXRhQ0VBMzlAbWV0YS5kYXRhCgojIFN0ZXAgMjogTWVyZ2Ugd2l0aCBkYXRhZnJhbWUgKHRlbXApIHdpdGggc2VsZWN0IHZhcmlhYmxlcyBiYXNlZCBvbiAnUGF0aWVudCcgY29sdW1uCm1lcmdlZF9tZXRhZGF0YV9kZiA8LSBtZXJnZShvcmlnaW5hbF9tZXRhZGF0YV9kZiwgdGVtcCwgYnkgPSAiUGF0aWVudCIsIGFsbC54ID0gVFJVRSwgc29ydCA9IEZBTFNFKQoKIyBTdGVwIDM6IEV4Y2x1ZGUgYWxyZWFkeSBleGlzdGluZyBjb2x1bW5zIHRvIGF2b2lkIGR1cGxpY2F0aW9uCm5ld19tZXRhZGF0YV9jb2x1bW5zIDwtIHNldGRpZmYoY29sbmFtZXModGVtcCksIGNvbG5hbWVzKG9yaWdpbmFsX21ldGFkYXRhX2RmKSkKbmV3X21ldGFfaW5mb19kZiA8LSBtZXJnZWRfbWV0YWRhdGFfZGZbLCBuZXdfbWV0YWRhdGFfY29sdW1ucywgZHJvcCA9IEZBTFNFXQoKIyBTdGVwIDQ6IEFkZCB0aGUgbmV3IG1ldGFkYXRhIHRvIHRoZSBTZXVyYXQgb2JqZWN0CnNjUk5Bc2VxRGF0YUNFQTM5IDwtIEFkZE1ldGFEYXRhKHNjUk5Bc2VxRGF0YUNFQTM5LCBtZXRhZGF0YSA9IG5ld19tZXRhX2luZm9fZGYpCgojIFN0ZXAgNTogUmVuYW1lIGBQYXRpZW50YCB0byBgU1RVRFlfTlVNQkVSYCB0byBtYXRjaCB0aGUgY2xpbmljYWwgZGF0YQpzY1JOQXNlcURhdGFDRUEzOUBtZXRhLmRhdGEgPC0gZHBseXI6OnJlbmFtZShzY1JOQXNlcURhdGFDRUEzOUBtZXRhLmRhdGEsICJTVFVEWV9OVU1CRVIiID0gIlBhdGllbnQiKQoKIyBWZXJpZnkgdGhhdCB0aGUgbmV3IG1ldGFkYXRhIHdhcyBhZGRlZCBjb3JyZWN0bHkKaGVhZChzY1JOQXNlcURhdGFDRUEzOUBtZXRhLmRhdGEpCgpgYGAKCiMjIFNhdmluZyBuZXcgZGF0YXNldAoKYGBge3J9CnRlbXAyIDwtIGFzX3RpYmJsZShzdWJzZXQoc2NSTkFzZXFEYXRhQ0VBMzlAbWV0YS5kYXRhLCBzZWxlY3QgPSBjKCJTVFVEWV9OVU1CRVIiLCAib3JpZy5pZGVudCIsICJuQ291bnRfUk5BIiwgIm5GZWF0dXJlX1JOQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBsYXRlIiwgIkJhdGNoIiwgIkMuSCIsICJUeXBlIiwgInBlcmNlbnQubXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuQ291bnRfU0NUIiwgIm5GZWF0dXJlX1NDVCIsICJzZXVyYXRfY2x1c3RlcnMiKSkpCgojIGZ3cml0ZSh0ZW1wMiwKIyAgICAgICAgZmlsZSA9IHBhc3RlMChPVVRfbG9jLCAiLyIsIFRvZGF5LCAiLkFFU0NSTkEuQ0VBLjM5cHRzLnNhbXBsZWxpc3QuYWZ0ZXJfcWMuSUNfY29tbWVyY2lhbC5jc3YiKSwKIyAgICAgICAgc2VwID0gIiwiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gVFJVRSwKIyAgICAgICAgc2hvd1Byb2dyZXNzID0gVFJVRSkKIyBybSh0ZW1wMikKIyAKIyB0ZW1wIDwtIGRwbHlyOjpyZW5hbWUodGVtcCwgIlNUVURZX05VTUJFUiIgPSAiUGF0aWVudCIpCiMgZndyaXRlKHRlbXAsCiMgICAgICAgIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5BRVNDUk5BLkNFQS4zOXB0cy5jbGluaWNhbGRhdGEuYWZ0ZXJfcWMuSUNfY29tbWVyY2lhbC5jc3YiKSwKIyAgICAgICAgc2VwID0gIiwiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gVFJVRSwKIyAgICAgICAgc2hvd1Byb2dyZXNzID0gVFJVRSkKIyBybSh0ZW1wKQojIAojIHNhdmVSRFMoc2NSTkFzZXFEYXRhQ0VBMzksIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5BRVNDUk5BLkNFQS4zOXB0cy5TZXVyYXQuYWZ0ZXJfcWMuSUNfY29tbWVyY2lhbC5SRFMiKSkKCmZ3cml0ZSh0ZW1wMiwKICAgICAgIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5BRVNDUk5BLkNFQS4zOXB0cy5zYW1wbGVsaXN0LmFmdGVyX3FjLklDX2FjYWRlbWljLmNzdiIpLAogICAgICAgc2VwID0gIiwiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gVFJVRSwKICAgICAgIHNob3dQcm9ncmVzcyA9IFRSVUUpCnJtKHRlbXAyKQoKdGVtcCA8LSBkcGx5cjo6cmVuYW1lKHRlbXAsICJTVFVEWV9OVU1CRVIiID0gIlBhdGllbnQiKQpmd3JpdGUodGVtcCwKICAgICAgIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5BRVNDUk5BLkNFQS4zOXB0cy5jbGluaWNhbGRhdGEuYWZ0ZXJfcWMuSUNfYWNhZGVtaWMuY3N2IiksCiAgICAgICBzZXAgPSAiLCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjb2wubmFtZXMgPSBUUlVFLAogICAgICAgc2hvd1Byb2dyZXNzID0gVFJVRSkKcm0odGVtcCkKCnNhdmVSRFMoc2NSTkFzZXFEYXRhQ0VBMzksIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5BRVNDUk5BLkNFQS4zOXB0cy5TZXVyYXQuYWZ0ZXJfcWMuSUNfYWNhZGVtaWMuUkRTIikpCgpgYGAKCgojIEFFU0NSTkEKCiMjIFF1YWxpdHkgY29udHJvbAoKSGVyZSByZXZpZXcgdGhlIG51bWJlciBvZiBjZWxscyBwZXIgc2FtcGxlLCBwbGF0ZSwgYW5kIHBhdGllbnRzLiBBbmQgcGxvdCB0aGUKcmF0aW8ncyBwZXIgc2FtcGxlIGFuZCBzdHVkeSBudW1iZXIuCgpgYGB7ciBRdWFsaXR5Q29udHJvbH0KIyMgY2hlY2sgc3R1ZmYKY2F0KCJcbkhvdyBtYW55IGNlbGxzIHBlciB0eXBlIC4uLj8iKQpzb3J0KHRhYmxlKHNjUk5Bc2VxRGF0YUNFQTM5QG1ldGEuZGF0YSRTQ1Rfc25uX3Jlcy4xLjI1KSkKCiMgY2F0KCJcblxuSG93IG1hbnkgY2VsbHMgcGVyIHBsYXRlIC4uLj8iKQojIHNvcnQodGFibGUoc2NSTkFzZXFEYXRhQ0VBMzlAbWV0YS5kYXRhJElEKSkKCiMgY2F0KCJcblxuSG93IG1hbnkgY2VsbHMgcGVyIHR5cGUgcGVyIHBsYXRlIC4uLj8iKQojIHRhYmxlKHNjUk5Bc2VxRGF0YUNFQTM5QG1ldGEuZGF0YSRTQ1Rfc25uX3Jlcy4wLjgsIHNjUk5Bc2VxRGF0YUNFQTM5QG1ldGEuZGF0YSRJRCkKCmNhdCgiXG5cbkhvdyBtYW55IGNlbGxzIHBlciBwYXRpZW50IC4uLj8iKQpzb3J0KHRhYmxlKHNjUk5Bc2VxRGF0YUNFQTM5QG1ldGEuZGF0YSRTVFVEWV9OVU1CRVIpKQoKY2F0KCJcblxuVmlzdWFsaXppbmcgdGhlc2UgcmF0aW8ncyBwZXIgc3R1ZHkgbnVtYmVyIGFuZCBzYW1wbGUgLi4uPyIpClVNQVBQbG90KHNjUk5Bc2VxRGF0YUNFQTM5LCBsYWJlbCA9IFRSVUUsIHB0LnNpemUgPSAxLjI1LCBsYWJlbC5zaXplID0gNCwgZ3JvdXAuYnkgPSAiaWRlbnQiLAogICAgICAgICByZXBlbCA9IFRSVUUpCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuVU1BUC5wbmciKSwgcGxvdCA9IGxhc3RfcGxvdCgpKQpnZ3NhdmUocGFzdGUwKFBMT1RfbG9jLCAiLyIsIFRvZGF5LCAiLlVNQVAucHMiKSwgcGxvdCA9IGxhc3RfcGxvdCgpKQoKCiMgYmFycGxvdChwcm9wLnRhYmxlKHggPSB0YWJsZShzY1JOQXNlcURhdGFDRUEzOUBhY3RpdmUuaWRlbnQsIHNjUk5Bc2VxRGF0YUNFQTM5QG1ldGEuZGF0YSRQYXRpZW50KSksIAojICAgICAgICAgY2V4LmF4aXMgPSAxLjAsIGNleC5uYW1lcyA9IDAuNSwgbGFzID0gMSwKIyAgICAgICAgIGNvbCA9IHVpdGhvZl9jb2xvciwgeGxhYiA9ICJzdHVkeSBudW1iZXIiLCBsZWdlbmQudGV4dCA9IEZBTFNFLCBhcmdzLmxlZ2VuZCA9IGxpc3QoeCA9ICJib3R0b20iKSkKIyBkZXYuY29weShwZGYsIHBhc3RlMChRQ19sb2MsICIvIiwgVG9kYXksICIuY2VsbF9yYXRpb3NfcGVyX3NhbXBsZS5wZGYiKSkKIyBkZXYub2ZmKCkKCiMgYmFycGxvdChwcm9wLnRhYmxlKHggPSB0YWJsZShzY1JOQXNlcURhdGFDRUEzOUBhY3RpdmUuaWRlbnQsIHNjUk5Bc2VxRGF0YUNFQTM5QG1ldGEuZGF0YSRJRCkpLCAKIyAgICAgICAgIGNleC5heGlzID0gMS4wLCBjZXgubmFtZXMgPSAwLjUsIGxhcyA9IDIsCiMgICAgICAgICBjb2wgPSB1aXRob2ZfY29sb3IsIHhsYWIgPSAic2FtcGxlIElEIiwgbGVnZW5kLnRleHQgPSBGQUxTRSwgYXJncy5sZWdlbmQgPSBsaXN0KHggPSAiYm90dG9tIikpCiMgZGV2LmNvcHkocGRmLCBwYXN0ZTAoUUNfbG9jLCAiLyIsIFRvZGF5LCAiLmNlbGxfcmF0aW9zX3Blcl9zYW1wbGVfcGVyX3BsYXRlLnBkZiIpKQojIGRldi5vZmYoKQoKYGBgCgojIyBWaXN1YWxpc2F0aW9ucwoKIyMjIEZlYXR1cmUgcGxvdHMgb2Yga25vd24gY2VsbHVsYXIgbWFya2VycwoKTGV0J3MgcHJvamVjdCBrbm93biBjZWxsdWxhciBtYXJrZXJzLgoKYGBge3IgVmlzdWFsaXNhdGlvbjogdFNORSBFeHBsb3JhdGlvbn0KVU1BUFBsb3Qoc2NSTkFzZXFEYXRhQ0VBMzksIGxhYmVsID0gRkFMU0UsIHB0LnNpemUgPSAxLjI1LCBsYWJlbC5zaXplID0gNCwgZ3JvdXAuYnkgPSAiaWRlbnQiLAogICAgICAgICByZXBlbCA9IFRSVUUpCgojIGVuZG90aGVsaWFsIGNlbGxzCkZlYXR1cmVQbG90KHNjUk5Bc2VxRGF0YUNFQTM5LCBmZWF0dXJlcyA9IGMoIkNEMzQiKSwgY29scyA9ICBjKCIjRUNFQ0VDIiwgIiNEQjAwM0YiKSkKRmVhdHVyZVBsb3Qoc2NSTkFzZXFEYXRhQ0VBMzksIGZlYXR1cmVzID0gYygiRUROMSIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJFRE5SQSIsICJFRE5SQiIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJDREg1IiwgIlBFQ0FNMSIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJBQ0tSMSIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQoKIyBTTUMKRmVhdHVyZVBsb3Qoc2NSTkFzZXFEYXRhQ0VBMzksIGZlYXR1cmVzID0gYygiTVlIMTEiKSwgY29scyA9ICBjKCIjRUNFQ0VDIiwgIiNEQjAwM0YiKSkKRmVhdHVyZVBsb3Qoc2NSTkFzZXFEYXRhQ0VBMzksIGZlYXR1cmVzID0gYygiTEdBTFMzIiwgIkFDVEEyIiksIGNvbHMgPSAgYygiI0VDRUNFQyIsICIjREIwMDNGIikpCgojIG1hY3JvcGhhZ2VzCkZlYXR1cmVQbG90KHNjUk5Bc2VxRGF0YUNFQTM5LCBmZWF0dXJlcyA9IGMoIkNEMTQiLCAiQ0Q2OCIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJDRDM2IiksIGNvbHMgPSAgYygiI0VDRUNFQyIsICIjREIwMDNGIikpCgojIHQtY2VsbHMKRmVhdHVyZVBsb3Qoc2NSTkFzZXFEYXRhQ0VBMzksIGZlYXR1cmVzID0gYygiQ0QzRSIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJDRDQiKSwgY29scyA9ICBjKCIjRUNFQ0VDIiwgIiNEQjAwM0YiKSkKIyBGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJDRDgiKSwgY29scyA9ICBjKCIjRUNFQ0VDIiwgIiNEQjAwM0YiKSkKCiMgYi1jZWxscwpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJDRDc5QSIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQoKIyBtYXN0IGNlbGxzCkZlYXR1cmVQbG90KHNjUk5Bc2VxRGF0YUNFQTM5LCBmZWF0dXJlcyA9IGMoIktJVCIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQoKIyBOSyBjZWxscwpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKCJOQ0FNMSIpLCBjb2xzID0gIGMoIiNFQ0VDRUMiLCAiI0RCMDAzRiIpKQoKYGBgCgojIyBUYXJnZXRzIG9mIGludGVyZXN0OgoKV2UgY2hlY2sgd2hldGhlciB0aGUgdGFyZ2V0cyBnZW5lcyB3ZXJlIHNlcXVlbmNlZCB1c2luZyBvdXIgbWV0aG9kLiBJbiBjYXNlIHNvbWUgZ2VuZXMgYXJlIG5vdCBhdmFpbGFibGUgaW4gb3VyIGRhdGEgd2UgY291bGQgZmlsdGVyIHRoZW0gaGVyZS4KCmBgYHtyIGxpc3QgdGFyZ2V0IGdlbmVzfQp0YXJnZXRfZ2VuZXMgPC0gZ2VuZV9saXN0CnRhcmdldF9nZW5lcwpgYGAKCgpUaGlzIGNvZGUgaXMganVzdCBhbiBleGFtcGxlIHRvIGZpbHRlciB0aGUgbGlzdCBmcm9tIGdlbmVzIHRoYXQgYXJlIG5vdCBpbiB0aGUgZGF0YS4KCi0gX05ENl8gPT0+IG5vdCBmb3VuZAotIF9UUklNNDlEMV8gPT0+IG5vdCBmb3VuZAotIF9ORDRMXyA9PT4gbm90IGZvdW5kCi0gX0FUUDhfID09PiBub3QgZm91bmQKLSBfUk5BU0UxXyA9PT4gbm90IGZvdW5kCgpgYGB7ciBWaXN1YWxpc2F0aW9uOiBwcmVwYXJhdGlvbn0KCmdlbmVfbGlzdF9ybSA8LSBjKCJORDYiLCAiVFJJTTQ5RDEiLAogICAgICAgICAgICAgICAgICAiTkQ0TCIsICJBVFA4IiwgIlJOQVNFMSIpIAoKdGVtcCA9IHRhcmdldF9nZW5lc1shdGFyZ2V0X2dlbmVzICVpbiUgZ2VuZV9saXN0X3JtXQoKdGFyZ2V0X2dlbmVzX3FjIDwtIGModGVtcCkKCiMgZ2VuZV9saXN0X3FjIDwtIGdlbmVfbGlzdAojIAojIGZvciBkZWJ1ZwojIGdlbmVfbGlzdF9xY19yZXBsYWNlIDwtIGMoIk1SVEZBIikKCiMgdGFyZ2V0X2dlbmVzX3FjIDwtIHRhcmdldF9nZW5lcwp0YXJnZXRfZ2VuZXNfcWMKCmBgYAoKCiMjIyBFeHByZXNzaW9uIGluIGNlbGwgY29tbXVuaXRpZXMKCmBgYHtyIFZpc3VhbGlzYXRpb246IFRhcmdldHMgRG90IFBsb3RzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKCnAxIDwtIERvdFBsb3Qoc2NSTkFzZXFEYXRhQ0VBMzksIAogICAgICAgICAgICAgIGZlYXR1cmVzID0gdGFyZ2V0X2dlbmVzX3FjLAogICAgICAgICAgICAgIGNvbHMgPSAiUmRCdSIpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MSwgc2l6ZSA9IDgpKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICMgcmVtb3ZlIHRoZSB5LSBhbmQgeC1heGlzIGxhYmVscwoKcDEKCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLnBuZyIpLCBwbG90ID0gbGFzdF9wbG90KCkpCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLnBzIiksIHBsb3QgPSBsYXN0X3Bsb3QoKSkKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Eb3RQbG90LlRhcmdldHMucGRmIiksIHBsb3QgPSBsYXN0X3Bsb3QoKSkKCnJtKHAxKQpgYGAKCkxldCdzIGdyb3VwIHRoaXMgZG90cGxvdCBiYXNlZCBvbiBzb21lIGdyb3VwaW5nLgoKSWYgd2Ugd2FudCB3ZSBjYW4gYWxzbyBmaWx0ZXIgdGhlIGdlbmVzIHRoYXQgYXJlIG5vdCBmb3VuZCBpbiB0aGUgZGF0YS4KCmBgYHtyfQojIEFzc3VtaW5nICdnZW5lX2xpc3RfZGYnIGlzIHlvdXIgZGF0YS5mcmFtZSB3aXRoIHRoZSByZWxldmFudCBjb2x1bW5zIGxvYWRlZApnZW5lX2xpc3RfZGZfZmlsdGVyZWQgPC0gc3Vic2V0KGdlbmVfbGlzdF9kZiwgQ29tbWVudHMgIT0gIm5vdCBmb3VuZCIgfCBpcy5uYShDb21tZW50cykpCmdlbmVfbGlzdF9kZl9maWx0ZXJlZApgYGAKCiMjIyBFeHByZXNzaW9uIGluIGNlbGwgY29tbXVuaXRpZXMgZ3JvdXBlZAoKYGBge3J9CiMgU2VwYXJhdGUgZ2VuZXMgYnkgc2lnbmlmaWNhbmNlCmdlbmVfbGlzdF9kZl9maWx0ZXJlZF91cCA8LSBnZW5lX2xpc3RfZGZfZmlsdGVyZWQkR2VuZVN5bWJvbFtnZW5lX2xpc3RfZGZfZmlsdGVyZWQkc2lnbmlmaWNhbmNlID09ICJVUCJdCmdlbmVfbGlzdF9kZl9maWx0ZXJlZF9kb3duIDwtIGdlbmVfbGlzdF9kZl9maWx0ZXJlZCRHZW5lU3ltYm9sW2dlbmVfbGlzdF9kZl9maWx0ZXJlZCRzaWduaWZpY2FuY2UgPT0gIkRPV04iXQoKIyBDb21iaW5lIHRoZSBnZW5lcywgZmlyc3QgRE9XTiB0aGVuIFVQIChvciB2aWNlIHZlcnNhIGJhc2VkIG9uIHByZWZlcmVuY2UpCm9yZGVyZWRfZ2VuZXNfcWMgPC0gYyhnZW5lX2xpc3RfZGZfZmlsdGVyZWRfdXAsIGdlbmVfbGlzdF9kZl9maWx0ZXJlZF9kb3duKQpgYGAKCgpgYGB7cn0KbGlicmFyeShSQ29sb3JCcmV3ZXIpCiMgQ3JlYXRlIERvdFBsb3Qgb3JkZXJlZApwMV9ncm91cCA8LSBEb3RQbG90KHNjUk5Bc2VxRGF0YSwgCiAgICAgICAgICAgICAgZmVhdHVyZXMgPSBvcmRlcmVkX2dlbmVzX3FjLCAKICAgICAgICAgICAgICBjb2xzID0gIlJkQnUiKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEsIHNpemUgPSA4KSkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSAjIHJlbW92ZSB0aGUgeS0gYW5kIHgtYXhpcyBsYWJlbHMKCnAxX2dyb3VwCgojIFNhdmUgdGhlIHBsb3RzCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkdyb3VwZWQucG5nIiksIHBsb3QgPSBwMV9ncm91cCkKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Eb3RQbG90LlRhcmdldHMuR3JvdXBlZC5wcyIpLCBwbG90ID0gcDFfZ3JvdXApCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkdyb3VwZWQucGRmIiksIHBsb3QgPSBwMV9ncm91cCkKCmBgYAoKIyMjIyBQbG90dGluZyBnZW5kZXIKCldlIHNob3VsZCBhbHNvIHBsb3QgdGhlc2UgZGF0YSBzdHJhdGlmaWVkIGJ5IGdlbmRlciBzbW9vdGggbXVzY2xlIGNlbGxzLgoKIyMjIyMgQ3JlYXRlIHN1YnNldHMKCmBgYHtyfQp1bmlxdWUoc2NSTkFzZXFEYXRhQ0VBMzkkR2VuZGVyKQpgYGAKCmBgYHtyfQojIFN1YnNldCBTZXVyYXQgb2JqZWN0IGZvciBNYWxlcwptYWxlX2NlbGxzIDwtIFdoaWNoQ2VsbHMoc2NSTkFzZXFEYXRhQ0VBMzksIGV4cHJlc3Npb24gPSBHZW5kZXIgPT0gIm1hbGUiKQpzY1JOQXNlcURhdGFDRUEzOV9tYWxlcyA8LSBzdWJzZXQoc2NSTkFzZXFEYXRhQ0VBMzksIGNlbGxzID0gbWFsZV9jZWxscykKCiMgU3Vic2V0IFNldXJhdCBvYmplY3QgZm9yIEZlbWFsZXMKZmVtYWxlX2NlbGxzIDwtIFdoaWNoQ2VsbHMoc2NSTkFzZXFEYXRhQ0VBMzksIGV4cHJlc3Npb24gPSBHZW5kZXIgPT0gImZlbWFsZSIpCnNjUk5Bc2VxRGF0YUNFQTM5X2ZlbWFsZXMgPC0gc3Vic2V0KHNjUk5Bc2VxRGF0YUNFQTM5LCBjZWxscyA9IGZlbWFsZV9jZWxscykKYGBgCgojIyMjIyBTbW9vdGggbXVzY2xlIGNlbGxzCgpHZXQgYW4gb3ZlcnZpZXcgb2YgdGhlIHZhcmlvdXMgY2VsbCBjb21tdW5pdGllcy4gCgpgYGB7cn0KdW5pcXVlKHNjUk5Bc2VxRGF0YUNFQTM5QGFjdGl2ZS5pZGVudCkKYGBgCgpTZWxlY3QgdGhlIGNlbGwgY29tbXVuaXR5IG9mIGludGVyZXN0IC0gaW4gdGhpcyBleGFtcGxlICdzbW9vdGggbXVzY2xlIGNlbGxzJyBkZWZpbmVkIGJ5IGBBQ1RBMisgU01DYC4KCmBgYHtyfQojIERlZmluZSB0aGUgY2VsbCBpZGVudGl0aWVzIHlvdSB3YW50IHRvIGluY2x1ZGUgaW4gdGhlIHBsb3QKc2VsZWN0ZWRfaWRlbnRzX2NlbGxzIDwtIGMoIkFDVEEyKyBTTUMiKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShjb3dwbG90KSAgIyBGb3IgY29tYmluaW5nIHBsb3RzCgojIENyZWF0ZSBEb3RQbG90IGZvciBtYWxlcwpwMV9tYWxlc19jZWxscyA8LSBEb3RQbG90KHNjUk5Bc2VxRGF0YUNFQTM5X21hbGVzLAogICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gb3JkZXJlZF9nZW5lc19xYywKICAgICAgICAgICAgICAgICAgICAgICBpZGVudHMgPSBzZWxlY3RlZF9pZGVudHNfY2VsbHMsIAogICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgIGNvbHMgPSAiUmRCdSIpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gOCkpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBnZ3RpdGxlKCJNYWxlcyIpCgojIENyZWF0ZSBEb3RQbG90IGZvciBmZW1hbGVzCnAyX2ZlbWFsZXNfY2VsbHMgPC0gRG90UGxvdChzY1JOQXNlcURhdGFDRUEzOV9mZW1hbGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IG9yZGVyZWRfZ2VuZXNfcWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50cyA9IHNlbGVjdGVkX2lkZW50c19jZWxscywKICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHMgPSAiUmRCdSIpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gOCkpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICAjIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAjICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAjICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLCAgIyBSZW1vdmUgeS1heGlzIHRleHQKICAjICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyAgIyBSZW1vdmUgeS1heGlzIHRpY2tzIAogIGdndGl0bGUoIkZlbWFsZXMiKQoKIyBDb21iaW5lIHRoZSB0d28gcGxvdHMgaW50byBvbmUgcGFuZWwgdXNpbmcgY293cGxvdApjb21iaW5lZF9wbG90X2NlbGxzIDwtIHBsb3RfZ3JpZChwMV9tYWxlc19jZWxscywgcDJfZmVtYWxlc19jZWxscywgbmNvbCA9IDIpCgojIERpc3BsYXkgdGhlIGNvbWJpbmVkIHBsb3QKcHJpbnQoY29tYmluZWRfcGxvdF9jZWxscykKCgojIFNhdmUgdGhlIHBsb3RzCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkNvbG9jR3JvdXBlZC5UQ2VsbG9ubHkuR2VuZGVyTWFsZXMucG5nIiksIHBsb3QgPSBwMV9tYWxlc19jZWxscykKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Eb3RQbG90LlRhcmdldHMuQ29sb2NHcm91cGVkLlRDZWxsb25seS5HZW5kZXJNYWxlcy5wcyIpLCBwbG90ID0gcDFfbWFsZXNfY2VsbHMpCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkNvbG9jR3JvdXBlZC5UQ2VsbG9ubHkuR2VuZGVyTWFsZXMucGRmIiksIHBsb3QgPSBwMV9tYWxlc19jZWxscykKCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkNvbG9jR3JvdXBlZC5UQ2VsbG9ubHkuR2VuZGVyRmVtYWxlcy5wbmciKSwgcGxvdCA9IHAyX2ZlbWFsZXNfY2VsbHMpCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkNvbG9jR3JvdXBlZC5UQ2VsbG9ubHkuR2VuZGVyRmVtYWxlcy5wcyIpLCBwbG90ID0gcDJfZmVtYWxlc19jZWxscykKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Eb3RQbG90LlRhcmdldHMuQ29sb2NHcm91cGVkLlRDZWxsb25seS5HZW5kZXJGZW1hbGVzLnBkZiIpLCBwbG90ID0gcDJfZmVtYWxlc19jZWxscykKCiMgZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Eb3RQbG90LlRhcmdldHMuQ29sb2NHcm91cGVkLlRDZWxsb25seS5HZW5kZXIucG5nIiksIHBsb3QgPSBjb21iaW5lZF9wbG90X2NlbGxzKQojIGdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkNvbG9jR3JvdXBlZC5UQ2VsbG9ubHkuR2VuZGVyLnBzIiksIHBsb3QgPSBjb21iaW5lZF9wbG90X2NlbGxzKQojIGdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRG90UGxvdC5UYXJnZXRzLkNvbG9jR3JvdXBlZC5UQ2VsbG9ubHkuR2VuZGVyLnBkZiIpLCBwbG90ID0gY29tYmluZWRfcGxvdF9jZWxscykKCmBgYAoKYGBge3IgVmlzdWFsaXNhdGlvbjogVGFyZ2V0cyBGZWF0dXJlIFBsb3RzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpGZWF0dXJlUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBjKHRhcmdldF9nZW5lc19xYyksCiAgICAgICAgICAgIGNvbHMgPSAgYygiI0VDRUNFQyIsICIjREIwMDNGIiwgIiM5QTM0ODAiLCIjMTI5MEQ5IiksCiAgICAgICAgICAgIGNvbWJpbmUgPSBUUlVFKQoKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5GZWF0dXJlUGxvdC5UYXJnZXRzLnBuZyIpLCBwbG90ID0gbGFzdF9wbG90KCkpCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuRmVhdHVyZVBsb3QuVGFyZ2V0cy5wcyIpLCBwbG90ID0gbGFzdF9wbG90KCkpCgpgYGAKCmBgYHtyIFZpc3VhbGlzYXRpb246IFRhcmdldHN9CiMgVmxuUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSAiRFVTUDI3IikKCiMgVmxuUGxvdCBmaWxlcwppZmVsc2UoIWRpci5leGlzdHMoZmlsZS5wYXRoKFBMT1RfbG9jLCAiL1ZsblBsb3QiKSksIAogICAgICAgZGlyLmNyZWF0ZShmaWxlLnBhdGgoUExPVF9sb2MsICIvVmxuUGxvdCIpKSwgCiAgICAgICBGQUxTRSkKVmxuUGxvdF9sb2MgPSBwYXN0ZTAoUExPVF9sb2MsICIvVmxuUGxvdCIpCgoKZm9yIChHRU5FIGluIHRhcmdldF9nZW5lc19xYyl7CiAgcHJpbnQocGFzdGUwKCJQcm9qZWN0aW5nIHRoZSBleHByZXNzaW9uIG9mICIsIEdFTkUsICIuIikpCgogIHZwMSA8LSAgVmxuUGxvdChzY1JOQXNlcURhdGFDRUEzOSwgZmVhdHVyZXMgPSBHRU5FKSArIAogICAgeGxhYigiY2VsbCBjb21tdW5pdGllcyIpICsgCiAgICB5bGFiKGJxdW90ZSgibm9ybWFsaXplZCBleHByZXNzaW9uIikpICsKICAgIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMDAwMDAwIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMDAwMDAwIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICAgIGdnc2F2ZShwYXN0ZTAoVmxuUGxvdF9sb2MsICIvIiwgVG9kYXksICIuVmxuUGxvdC4iLEdFTkUsIi5wbmciKSwgcGxvdCA9IGxhc3RfcGxvdCgpKQogICAgZ2dzYXZlKHBhc3RlMChWbG5QbG90X2xvYywgIi8iLCBUb2RheSwgIi5WbG5QbG90LiIsR0VORSwiLnBzIiksIHBsb3QgPSBsYXN0X3Bsb3QoKSkKICAgIGdnc2F2ZShwYXN0ZTAoVmxuUGxvdF9sb2MsICIvIiwgVG9kYXksICIuVmxuUGxvdC4iLEdFTkUsIi5wZGYiKSwgcGxvdCA9IGxhc3RfcGxvdCgpKQogIAogICMgcHJpbnQodnAxKQogIAp9CgpgYGAKCiMjIyBEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBiZXR3ZWVuIGNlbGwgY29tbXVuaXRpZXMKCkhlcmUgd2UgcHJvamVjdCBnZW5lcyB0byBvbmx5IHRoZSBicm9hZCBjZWxsIGNvbW11bml0aWVzOgoKLSAgIG1hY3JvcGhhZ2VzCi0gICBlbmRvdGhlbGlhbCBjZWxscwotICAgc21vb3RoIG11c2NsZSBjZWxscwotICAgVC1jZWxscwotICAgQi1jZWxscwotICAgTWFzdCBjZWxscwotICAgTkstY2VsbHMKLSAgIE1peGVkIGNlbGxzCgojIyMjIE1hY3JvcGhhZ2VzCgpgYGB7cn0KdW5pcXVlKHNjUk5Bc2VxRGF0YUNFQTM5QGFjdGl2ZS5pZGVudCkKYGBgCgpDb21wYXJpc29uIGJldHdlZW4gdGhlIG1hY3JvcGhhZ2VzIGNlbGwgY29tbXVuaXRpZXMgKCpDRDE0L0NENjgqPHN1cD4rPC9zdXA+KSwKYW5kIGFsbCBvdGhlciBjb21tdW5pdGllcy4KCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gTUFDIGNhbGN1bGF0ZX0KCk1BQy5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHNjUk5Bc2VxRGF0YUNFQTM5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NEMUMrIERDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrQ0Q0KyBNb25vIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtJTDE4K1RMUjQrVFJFTTIrIE1SZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0FCQ0ExK09MUjErVFJFTTIrIEZDIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjIgPSBjKCMiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMiQ0Q2OCtDRDFDKyBEQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMiQ0Q2OCtDRDQrIE1vbm8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMiQ0Q2OCtJTDE4K1RMUjQrVFJFTTIrIE1SZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMiQ0Q2OCtBQkNBMStPTFIxK1RSRU0yKyBGQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBWSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGT1hQMysgVEMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzNCsgRUMgSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDM0KyBFQyBJSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFDVEEyKyBTTUMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzK0NENTYrIE5LIEkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtLSVQrIE1DIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q3OSsgQkNwbGFzbWEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q3OUErIEJDbWVtIikpCgpEVDo6ZGF0YXRhYmxlKE1BQy5tYXJrZXJzKQpgYGAKCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gTUFDLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpNQUNfVm9sY2Fub19UYXJnZXRzQSA9IEVuaGFuY2VkVm9sY2FubyhNQUMubWFya2VycywKICAgIGxhYiA9IHJvd25hbWVzKE1BQy5tYXJrZXJzKSwKICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICB5ID0gInBfdmFsX2FkaiIsCiAgICBzZWxlY3RMYWIgPSB0YXJnZXRfZ2VuZXNfcWMsCiAgICBheGlzTGFiU2l6ZSA9IDEyLAogICAgeGxhYiA9ICJhdmVyYWdlIGZvbGQtY2hhbmdlIiwKICAgIHRpdGxlID0gIk1hY3JvcGhhZ2UgbWFya2Vyc1xuKE1hY3JvcGhhZ2UgY29tbXVuaXRpZXMgdnMgdGhlIHJlc3QpIiwKICAgIHRpdGxlTGFiU2l6ZSA9IDE0LAogICAgcEN1dG9mZiA9IDAuMDUvKG5yb3coTUFDLm1hcmtlcnMpKSwgIyAyMDU1MiBnZW5lcwogICAgRkNjdXRvZmYgPSAxLjI1LAogICAgcG9pbnRTaXplID0gMS41LAogICAgbGFiU2l6ZSA9IDMuMCwKICAgIGxlZ2VuZExhYmVscyA9YygnTlMnLCdhdmcuIGZvbGQtY2hhbmdlJywnUCcsCiAgICAgICdQICYgYXZnLiBmb2xkLWNoYW5nZScpLAogICAgbGVnZW5kUG9zaXRpb24gPSAicmlnaHQiLAogICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgbGVnZW5kSWNvblNpemUgPSAzLjAsCiAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjIsCiAgICBjb2xDb25uZWN0b3JzID0gIiM1OTVBNUMiLAogICAgZ3JpZGxpbmVzLm1ham9yID0gRkFMU0UsCiAgICBncmlkbGluZXMubWlub3IgPSBGQUxTRSkKTUFDX1ZvbGNhbm9fVGFyZ2V0c0EKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Wb2xjYW5vLk1BQy5ERUcuVGFyZ2V0cy5wZGYiKSwgCiAgICAgICBwbG90ID0gTUFDX1ZvbGNhbm9fVGFyZ2V0c0EpCmBgYAoKVGhlIHRhcmdldCByZXN1bHRzIGFyZSBnaXZlbiBiZWxvdyBhbmQgd3JpdHRlbiB0byBhIGZpbGUuCgpgYGB7ciBSZXN1bHRzIE1BQ30KbGlicmFyeSh0aWJibGUpCk1BQy5tYXJrZXJzIDwtIGFkZF9jb2x1bW4oTUFDLm1hcmtlcnMsIEdlbmUgPSByb3cubmFtZXMoTUFDLm1hcmtlcnMpLCAuYmVmb3JlID0gMSkKCnRlbXAgPC0gTUFDLm1hcmtlcnNbTUFDLm1hcmtlcnMkR2VuZSAlaW4lIHRhcmdldF9nZW5lc19xYyxdCgpEVDo6ZGF0YXRhYmxlKHRlbXApCmBgYAoKYGBge3IgUmVzdWx0cyBNQUM6IHdyaXRpbmd9CmZ3cml0ZSh0ZW1wLCBmaWxlID0gcGFzdGUwKE9VVF9sb2MsICIvIiwgVG9kYXksICIuTUFDLkRFRy5UYXJnZXRzLnR4dCIpLAogICAgICAgcXVvdGUgPSBGQUxTRSwKICAgICAgIHNlcCA9ICJcdCIsIAogICAgICAgc2hvd1Byb2dyZXNzID0gRkFMU0UsIHZlcmJvc2UgPSBGQUxTRSkKYGBgCgojIyMjIFNtb290aCBtdXNjbGUgY2VsbHMKCkNvbXBhcmlzb24gYmV0d2VlbiB0aGUgc21vb3RoIG11c2NsZSBjZWxsIGNvbW11bml0aWVzICgqQUNUQTIqPHN1cD4rPC9zdXA+KSwgYW5kCmFsbCBvdGhlciBjb21tdW5pdGllcy4KCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gU01DIGNhbGN1bGF0ZX0KClNNQy5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHNjUk5Bc2VxRGF0YUNFQTM5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiQUNUQTIrIFNNQyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYygiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NEMUMrIERDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrQ0Q0KyBNb25vIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtJTDE4K1RMUjQrVFJFTTIrIE1SZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0FCQ0ExK09MUjErVFJFTTIrIEZDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElWIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFZJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZPWFAzKyBUQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDM0KyBFQyBJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMzQrIEVDIElJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIkFDVEEyKyBTTUMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzK0NENTYrIE5LIEkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtLSVQrIE1DIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q3OSsgQkNwbGFzbWEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q3OUErIEJDbWVtIikpCgpEVDo6ZGF0YXRhYmxlKFNNQy5tYXJrZXJzKQpgYGAKCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gU01DLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpTTUNfVm9sY2Fub19UYXJnZXRzQSA9IEVuaGFuY2VkVm9sY2FubyhTTUMubWFya2VycywKICAgIGxhYiA9IHJvd25hbWVzKFNNQy5tYXJrZXJzKSwKICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICB5ID0gInBfdmFsX2FkaiIsCiAgICBzZWxlY3RMYWIgPSB0YXJnZXRfZ2VuZXNfcWMsCiAgICBheGlzTGFiU2l6ZSA9IDEyLAogICAgeGxhYiA9ICJhdmVyYWdlIGZvbGQtY2hhbmdlIiwKICAgIHRpdGxlID0gIlNNQyBtYXJrZXJzXG4oU01DIGNvbW11bml0aWVzIHZzIHRoZSByZXN0KSIsCiAgICB0aXRsZUxhYlNpemUgPSAxNCwKICAgIHBDdXRvZmYgPSAwLjA1Lyhucm93KFNNQy5tYXJrZXJzKSksICMgMjA1NTIgZ2VuZXMKICAgIEZDY3V0b2ZmID0gMS4yNSwKICAgIHBvaW50U2l6ZSA9IDEuNSwKICAgIGxhYlNpemUgPSAzLjAsCiAgICBsZWdlbmRMYWJlbHMgPWMoJ05TJywnYXZnLiBmb2xkLWNoYW5nZScsJ1AnLAogICAgICAnUCAmIGF2Zy4gZm9sZC1jaGFuZ2UnKSwKICAgIGxlZ2VuZFBvc2l0aW9uID0gInJpZ2h0IiwKICAgIGxlZ2VuZExhYlNpemUgPSAxMCwKICAgIGxlZ2VuZEljb25TaXplID0gMy4wLAogICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgd2lkdGhDb25uZWN0b3JzID0gMC4yLAogICAgY29sQ29ubmVjdG9ycyA9ICIjNTk1QTVDIiwKICAgIGdyaWRsaW5lcy5tYWpvciA9IEZBTFNFLAogICAgZ3JpZGxpbmVzLm1pbm9yID0gRkFMU0UpClNNQ19Wb2xjYW5vX1RhcmdldHNBCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuVm9sY2Fuby5TTUMuREVHLlRhcmdldHMucGRmIiksIAogICAgICAgcGxvdCA9IFNNQ19Wb2xjYW5vX1RhcmdldHNBKQpgYGAKClRoZSB0YXJnZXQgcmVzdWx0cyBhcmUgZ2l2ZW4gYmVsb3cgYW5kIHdyaXR0ZW4gdG8gYSBmaWxlLgoKYGBge3IgUmVzdWx0cyBTTUN9CmxpYnJhcnkodGliYmxlKQpTTUMubWFya2VycyA8LSBhZGRfY29sdW1uKFNNQy5tYXJrZXJzLCBHZW5lID0gcm93Lm5hbWVzKFNNQy5tYXJrZXJzKSwgLmJlZm9yZSA9IDEpCgp0ZW1wIDwtIFNNQy5tYXJrZXJzW1NNQy5tYXJrZXJzJEdlbmUgJWluJSB0YXJnZXRfZ2VuZXNfcWMsXQoKRFQ6OmRhdGF0YWJsZSh0ZW1wKQpgYGAKCmBgYHtyIFJlc3VsdHMgU01DOiB3cml0aW5nfQpmd3JpdGUodGVtcCwgZmlsZSA9IHBhc3RlMChPVVRfbG9jLCAiLyIsIFRvZGF5LCAiLlNNQy5ERUcuVGFyZ2V0cy50eHQiKSwKICAgICAgIHF1b3RlID0gRkFMU0UsCiAgICAgICBzZXAgPSAiXHQiLCAKICAgICAgIHNob3dQcm9ncmVzcyA9IEZBTFNFLCB2ZXJib3NlID0gRkFMU0UpCmBgYAoKIyMjIyBFbmRvdGhlbGlhbCBjZWxscwoKQ29tcGFyaXNvbiBiZXR3ZWVuIHRoZSBlbmRvdGhlbGlhbCBjZWxsIGNvbW11bml0aWVzICgqQ0QzNCo8c3VwPis8L3N1cD4pLCBhbmQKYWxsIG90aGVyIGNvbW11bml0aWVzLgoKYGBge3IgVmlzdWFsaXNhdGlvbjogVm9sY2FubyBFQyBjYWxjdWxhdGV9CgpFQy5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHNjUk5Bc2VxRGF0YUNFQTM5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiQ0QzNCsgRUMgSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDM0KyBFQyBJSSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYygiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NEMUMrIERDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrQ0Q0KyBNb25vIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtJTDE4K1RMUjQrVFJFTTIrIE1SZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0FCQ0ExK09MUjErVFJFTTIrIEZDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElWIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFZJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZPWFAzKyBUQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIkNEMzQrIEVDIEkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJDRDM0KyBFQyBJSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFDVEEyKyBTTUMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzK0NENTYrIE5LIEkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtLSVQrIE1DIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q3OSsgQkNwbGFzbWEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q3OUErIEJDbWVtIikpCgpEVDo6ZGF0YXRhYmxlKEVDLm1hcmtlcnMpCmBgYAoKYGBge3IgVmlzdWFsaXNhdGlvbjogVm9sY2FubyBFQywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRUNfVm9sY2Fub19UYXJnZXRzQSA9IEVuaGFuY2VkVm9sY2FubyhFQy5tYXJrZXJzLAogICAgbGFiID0gcm93bmFtZXMoRUMubWFya2VycyksCiAgICB4ID0gImF2Z19sb2cyRkMiLAogICAgeSA9ICJwX3ZhbF9hZGoiLAogICAgc2VsZWN0TGFiID0gdGFyZ2V0X2dlbmVzX3FjLAogICAgYXhpc0xhYlNpemUgPSAxMiwKICAgIHhsYWIgPSAiYXZlcmFnZSBmb2xkLWNoYW5nZSIsCiAgICB0aXRsZSA9ICJFbmRvdGhlbGlhbCBjZWxsIG1hcmtlcnNcbihFQyBjb21tdW5pdGllcyB2cyB0aGUgcmVzdCkiLAogICAgdGl0bGVMYWJTaXplID0gMTQsCiAgICBwQ3V0b2ZmID0gMC4wNS8obnJvdyhFQy5tYXJrZXJzKSksICMgMjA1NTIgZ2VuZXMKICAgIEZDY3V0b2ZmID0gMS4yNSwKICAgIHBvaW50U2l6ZSA9IDEuNSwKICAgIGxhYlNpemUgPSAzLjAsCiAgICBsZWdlbmRMYWJlbHMgPWMoJ05TJywnYXZnLiBmb2xkLWNoYW5nZScsJ1AnLAogICAgICAnUCAmIGF2Zy4gZm9sZC1jaGFuZ2UnKSwKICAgIGxlZ2VuZFBvc2l0aW9uID0gInJpZ2h0IiwKICAgIGxlZ2VuZExhYlNpemUgPSAxMCwKICAgIGxlZ2VuZEljb25TaXplID0gMy4wLAogICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgd2lkdGhDb25uZWN0b3JzID0gMC4yLAogICAgY29sQ29ubmVjdG9ycyA9ICIjNTk1QTVDIiwKICAgIGdyaWRsaW5lcy5tYWpvciA9IEZBTFNFLAogICAgZ3JpZGxpbmVzLm1pbm9yID0gRkFMU0UpCkVDX1ZvbGNhbm9fVGFyZ2V0c0EKZ2dzYXZlKHBhc3RlMChQTE9UX2xvYywgIi8iLCBUb2RheSwgIi5Wb2xjYW5vLkVDLkRFRy5UYXJnZXRzLnBkZiIpLCAKICAgICAgIHBsb3QgPSBFQ19Wb2xjYW5vX1RhcmdldHNBKQpgYGAKClRoZSB0YXJnZXQgcmVzdWx0cyBhcmUgZ2l2ZW4gYmVsb3cgYW5kIHdyaXR0ZW4gdG8gYSBmaWxlLgoKYGBge3IgUmVzdWx0cyBFQ30KbGlicmFyeSh0aWJibGUpCkVDLm1hcmtlcnMgPC0gYWRkX2NvbHVtbihFQy5tYXJrZXJzLCBHZW5lID0gcm93Lm5hbWVzKEVDLm1hcmtlcnMpLCAuYmVmb3JlID0gMSkKCnRlbXAgPC0gRUMubWFya2Vyc1tFQy5tYXJrZXJzJEdlbmUgJWluJSB0YXJnZXRfZ2VuZXNfcWMsXQoKRFQ6OmRhdGF0YWJsZSh0ZW1wKQpgYGAKCmBgYHtyIFJlc3VsdHMgRUM6IHdyaXRpbmd9CmZ3cml0ZSh0ZW1wLCBmaWxlID0gcGFzdGUwKE9VVF9sb2MsICIvIiwgVG9kYXksICIuRUMuREVHLlRhcmdldHMudHh0IiksCiAgICAgICBxdW90ZSA9IEZBTFNFLAogICAgICAgc2VwID0gIlx0IiwgCiAgICAgICBzaG93UHJvZ3Jlc3MgPSBGQUxTRSwgdmVyYm9zZSA9IEZBTFNFKQpgYGAKCiMjIyMgVC1jZWxscwoKQ29tcGFyaXNvbiBiZXR3ZWVuIHRoZSBULWNlbGwgY29tbXVuaXRpZXMgKCpDRDMvQ0Q0L0NEOCo8c3VwPis8L3N1cD4pLCBhbmQgYWxsCm90aGVyIGNvbW11bml0aWVzLgoKYGBge3IgVmlzdWFsaXNhdGlvbjogVm9sY2FubyBUY2VsbCBjYWxjdWxhdGV9CgpUQy5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHNjUk5Bc2VxRGF0YUNFQTM5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiQ0QzKyBUQyBJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElWIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFZJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZPWFAzKyBUQyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYygiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NEMUMrIERDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrQ0Q0KyBNb25vIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtJTDE4K1RMUjQrVFJFTTIrIE1SZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0FCQ0ExK09MUjErVFJFTTIrIEZDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJDRDMrIFRDIEkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIkNEMysgVEMgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJDRDMrIFRDIElJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIkNEMysgVEMgSVYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJDRDMrIFRDIFYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJDRDMrIFRDIFZJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAiRk9YUDMrIFRDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMzQrIEVDIEkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzNCsgRUMgSUkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBQ1RBMisgU01DIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMytDRDU2KyBOSyBJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzK0NENTYrIE5LIElJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrS0lUKyBNQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENzkrIEJDcGxhc21hIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENzlBKyBCQ21lbSIpKQoKRFQ6OmRhdGF0YWJsZShUQy5tYXJrZXJzKQpgYGAKCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gVGNlbGwsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClRDX1ZvbGNhbm9fVGFyZ2V0c0EgPSBFbmhhbmNlZFZvbGNhbm8oVEMubWFya2VycywKICAgIGxhYiA9IHJvd25hbWVzKFRDLm1hcmtlcnMpLAogICAgeCA9ICJhdmdfbG9nMkZDIiwKICAgIHkgPSAicF92YWxfYWRqIiwKICAgIHNlbGVjdExhYiA9IHRhcmdldF9nZW5lc19xYywKICAgIGF4aXNMYWJTaXplID0gMTIsCiAgICB4bGFiID0gImF2ZXJhZ2UgZm9sZC1jaGFuZ2UiLAogICAgdGl0bGUgPSAiVC1jZWxsIG1hcmtlcnNcbihULWNlbGwgY29tbXVuaXRpZXMgdnMgdGhlIHJlc3QpIiwKICAgIHRpdGxlTGFiU2l6ZSA9IDE0LAogICAgcEN1dG9mZiA9IDAuMDUvbnJvdyhUQy5tYXJrZXJzKSwgIyAyMDU1MiBnZW5lcwogICAgRkNjdXRvZmYgPSAxLjI1LAogICAgcG9pbnRTaXplID0gMS41LAogICAgbGFiU2l6ZSA9IDMuMCwKICAgIGxlZ2VuZExhYmVscyA9YygnTlMnLCdhdmcuIGZvbGQtY2hhbmdlJywnUCcsCiAgICAgICdQICYgYXZnLiBmb2xkLWNoYW5nZScpLAogICAgbGVnZW5kUG9zaXRpb24gPSAicmlnaHQiLAogICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgbGVnZW5kSWNvblNpemUgPSAzLjAsCiAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjIsCiAgICBjb2xDb25uZWN0b3JzID0gIiM1OTVBNUMiLAogICAgZ3JpZGxpbmVzLm1ham9yID0gRkFMU0UsCiAgICBncmlkbGluZXMubWlub3IgPSBGQUxTRSkKVENfVm9sY2Fub19UYXJnZXRzQQpnZ3NhdmUocGFzdGUwKFBMT1RfbG9jLCAiLyIsIFRvZGF5LCAiLlZvbGNhbm8uVEMuREVHLlRhcmdldHMucGRmIiksIAogICAgICAgcGxvdCA9IFRDX1ZvbGNhbm9fVGFyZ2V0c0EpCmBgYAoKVGhlIHRhcmdldCByZXN1bHRzIGFyZSBnaXZlbiBiZWxvdyBhbmQgd3JpdHRlbiB0byBhIGZpbGUuCgpgYGB7ciBSZXN1bHRzIFRDfQpsaWJyYXJ5KHRpYmJsZSkKVEMubWFya2VycyA8LSBhZGRfY29sdW1uKFRDLm1hcmtlcnMsIEdlbmUgPSByb3cubmFtZXMoVEMubWFya2VycyksIC5iZWZvcmUgPSAxKQoKdGVtcCA8LSBUQy5tYXJrZXJzW1RDLm1hcmtlcnMkR2VuZSAlaW4lIHRhcmdldF9nZW5lc19xYyxdCgpEVDo6ZGF0YXRhYmxlKHRlbXApCmBgYAoKYGBge3IgUmVzdWx0cyBUQzogd3JpdGluZ30KZndyaXRlKHRlbXAsIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5UQy5ERUcuVGFyZ2V0cy50eHQiKSwKICAgICAgIHF1b3RlID0gRkFMU0UsCiAgICAgICBzZXAgPSAiXHQiLCAKICAgICAgIHNob3dQcm9ncmVzcyA9IEZBTFNFLCB2ZXJib3NlID0gRkFMU0UpCmBgYAoKIyMjIyBCLWNlbGxzCgpDb21wYXJpc29uIGJldHdlZW4gdGhlIEItY2VsbCBjb21tdW5pdGllcyAoKkNENzlBKjxzdXA+Kzwvc3VwPiksIGFuZCBhbGwgb3RoZXIKY29tbXVuaXRpZXMuCgpgYGB7ciBWaXN1YWxpc2F0aW9uOiBWb2xjYW5vIEJjZWxsIGNhbGN1bGF0ZX0KCkJDLm1hcmtlcnMgPC0gRmluZE1hcmtlcnMob2JqZWN0ID0gc2NSTkFzZXFEYXRhQ0VBMzksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjEgPSBjKCJDRDc5KyBCQ3BsYXNtYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDc5QSsgQkNtZW0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQuMiA9IGMoIkNENjgrQ0FTUDErSUwxQitTRUxMIE1JbmYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtDRDFDKyBEQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NENCsgTW9ubyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrSUwxOCtUTFI0K1RSRU0yKyBNUmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtBQkNBMStPTFIxK1RSRU0yKyBGQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBWSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGT1hQMysgVEMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzNCsgRUMgSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDM0KyBFQyBJSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFDVEEyKyBTTUMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzK0NENTYrIE5LIEkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtLSVQrIE1DIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIkNENzkrIEJDcGxhc21hIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAiQ0Q3OUErIEJDbWVtIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpCgpEVDo6ZGF0YXRhYmxlKEJDLm1hcmtlcnMpCmBgYAoKYGBge3IgVmlzdWFsaXNhdGlvbjogVm9sY2FubyBCY2VsbCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KQkNfVm9sY2Fub19UYXJnZXRzQSA9IEVuaGFuY2VkVm9sY2FubyhCQy5tYXJrZXJzLAogICAgbGFiID0gcm93bmFtZXMoQkMubWFya2VycyksCiAgICB4ID0gImF2Z19sb2cyRkMiLAogICAgeSA9ICJwX3ZhbF9hZGoiLAogICAgc2VsZWN0TGFiID0gdGFyZ2V0X2dlbmVzX3FjLAogICAgYXhpc0xhYlNpemUgPSAxMiwKICAgIHhsYWIgPSAiYXZlcmFnZSBmb2xkLWNoYW5nZSIsCiAgICB0aXRsZSA9ICJCLWNlbGwgbWFya2Vyc1xuKEItY2VsbCBjb21tdW5pdGllcyB2cyB0aGUgcmVzdCkiLAogICAgdGl0bGVMYWJTaXplID0gMTQsCiAgICBwQ3V0b2ZmID0gMC4wNS9ucm93KEJDLm1hcmtlcnMpLCAjIDIwNTUyIGdlbmVzCiAgICBGQ2N1dG9mZiA9IDEuMjUsCiAgICBwb2ludFNpemUgPSAxLjUsCiAgICBsYWJTaXplID0gMy4wLAogICAgbGVnZW5kTGFiZWxzID1jKCdOUycsJ2F2Zy4gZm9sZC1jaGFuZ2UnLCdQJywKICAgICAgJ1AgJiBhdmcuIGZvbGQtY2hhbmdlJyksCiAgICBsZWdlbmRQb3NpdGlvbiA9ICJyaWdodCIsCiAgICBsZWdlbmRMYWJTaXplID0gMTAsCiAgICBsZWdlbmRJY29uU2l6ZSA9IDMuMCwKICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMiwKICAgIGNvbENvbm5lY3RvcnMgPSAiIzU5NUE1QyIsCiAgICBncmlkbGluZXMubWFqb3IgPSBGQUxTRSwKICAgIGdyaWRsaW5lcy5taW5vciA9IEZBTFNFKQpCQ19Wb2xjYW5vX1RhcmdldHNBCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuVm9sY2Fuby5CQy5ERUcuVGFyZ2V0cy5wZGYiKSwgCiAgICAgICBwbG90ID0gQkNfVm9sY2Fub19UYXJnZXRzQSkKYGBgCgpUaGUgdGFyZ2V0IHJlc3VsdHMgYXJlIGdpdmVuIGJlbG93IGFuZCB3cml0dGVuIHRvIGEgZmlsZS4KCmBgYHtyIFJlc3VsdHMgQkN9CmxpYnJhcnkodGliYmxlKQpCQy5tYXJrZXJzIDwtIGFkZF9jb2x1bW4oQkMubWFya2VycywgR2VuZSA9IHJvdy5uYW1lcyhCQy5tYXJrZXJzKSwgLmJlZm9yZSA9IDEpCgp0ZW1wIDwtIEJDLm1hcmtlcnNbQkMubWFya2VycyRHZW5lICVpbiUgdGFyZ2V0X2dlbmVzX3FjLF0KCkRUOjpkYXRhdGFibGUodGVtcCkKYGBgCgpgYGB7ciBSZXN1bHRzIEJDOiB3cml0aW5nfQpmd3JpdGUodGVtcCwgZmlsZSA9IHBhc3RlMChPVVRfbG9jLCAiLyIsIFRvZGF5LCAiLkJDLkRFRy5UYXJnZXRzLnR4dCIpLAogICAgICAgcXVvdGUgPSBGQUxTRSwKICAgICAgIHNlcCA9ICJcdCIsIAogICAgICAgc2hvd1Byb2dyZXNzID0gRkFMU0UsIHZlcmJvc2UgPSBGQUxTRSkKYGBgCgojIyMjIE1hc3QgY2VsbHMKCkNvbXBhcmlzb24gYmV0d2VlbiB0aGUgbWFzdCBjZWxsIGNvbW11bml0aWVzICgqS0lUKjxzdXA+Kzwvc3VwPiksIGFuZCBhbGwgb3RoZXIKY29tbXVuaXRpZXMuCgpgYGB7ciBWaXN1YWxpc2F0aW9uOiBWb2xjYW5vIE1hc3QgY2FsY3VsYXRlfQoKTUMubWFya2VycyA8LSBGaW5kTWFya2VycyhvYmplY3QgPSBzY1JOQXNlcURhdGFDRUEzOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQuMSA9IGMoIkNENjgrS0lUKyBNQyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYygiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NEMUMrIERDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrQ0Q0KyBNb25vIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtJTDE4K1RMUjQrVFJFTTIrIE1SZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0FCQ0ExK09MUjErVFJFTTIrIEZDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIElWIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFZJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZPWFAzKyBUQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDM0KyBFQyBJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMzQrIEVDIElJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQUNUQTIrIFNNQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMytDRDU2KyBOSyBJSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIkNENjgrS0lUKyBNQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENzkrIEJDcGxhc21hIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENzlBKyBCQ21lbSIpKQoKRFQ6OmRhdGF0YWJsZShNQy5tYXJrZXJzKQpgYGAKCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gTWFzdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KTUNfVm9sY2Fub19UYXJnZXRzQSA9IEVuaGFuY2VkVm9sY2FubyhNQy5tYXJrZXJzLAogICAgbGFiID0gcm93bmFtZXMoTUMubWFya2VycyksCiAgICB4ID0gImF2Z19sb2cyRkMiLAogICAgeSA9ICJwX3ZhbF9hZGoiLAogICAgc2VsZWN0TGFiID0gdGFyZ2V0X2dlbmVzX3FjLAogICAgYXhpc0xhYlNpemUgPSAxMiwKICAgIHhsYWIgPSAiYXZlcmFnZSBmb2xkLWNoYW5nZSIsCiAgICB0aXRsZSA9ICJNYXN0IGNlbGwgbWFya2Vyc1xuKE1hc3QgY2VsbCBjb21tdW5pdGllcyB2cyB0aGUgcmVzdCkiLAogICAgdGl0bGVMYWJTaXplID0gMTQsCiAgICBwQ3V0b2ZmID0gMC4wNS9ucm93KE1DLm1hcmtlcnMpLCAjIDIwNTUyIGdlbmVzCiAgICBGQ2N1dG9mZiA9IDEuMjUsCiAgICBwb2ludFNpemUgPSAxLjUsCiAgICBsYWJTaXplID0gMy4wLAogICAgbGVnZW5kTGFiZWxzID1jKCdOUycsJ2F2Zy4gZm9sZC1jaGFuZ2UnLCdQJywKICAgICAgJ1AgJiBhdmcuIGZvbGQtY2hhbmdlJyksCiAgICBsZWdlbmRQb3NpdGlvbiA9ICJyaWdodCIsCiAgICBsZWdlbmRMYWJTaXplID0gMTAsCiAgICBsZWdlbmRJY29uU2l6ZSA9IDMuMCwKICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMiwKICAgIGNvbENvbm5lY3RvcnMgPSAiIzU5NUE1QyIsCiAgICBncmlkbGluZXMubWFqb3IgPSBGQUxTRSwKICAgIGdyaWRsaW5lcy5taW5vciA9IEZBTFNFKQpNQ19Wb2xjYW5vX1RhcmdldHNBCmdnc2F2ZShwYXN0ZTAoUExPVF9sb2MsICIvIiwgVG9kYXksICIuVm9sY2Fuby5NQy5ERUcuVGFyZ2V0cy5wZGYiKSwgCiAgICAgICBwbG90ID0gTUNfVm9sY2Fub19UYXJnZXRzQSkKYGBgCgpUaGUgdGFyZ2V0IHJlc3VsdHMgYXJlIGdpdmVuIGJlbG93IGFuZCB3cml0dGVuIHRvIGEgZmlsZS4KCmBgYHtyIFJlc3VsdHMgTUN9CmxpYnJhcnkodGliYmxlKQpNQy5tYXJrZXJzIDwtIGFkZF9jb2x1bW4oTUMubWFya2VycywgR2VuZSA9IHJvdy5uYW1lcyhNQy5tYXJrZXJzKSwgLmJlZm9yZSA9IDEpCgp0ZW1wIDwtIE1DLm1hcmtlcnNbTUMubWFya2VycyRHZW5lICVpbiUgdGFyZ2V0X2dlbmVzX3FjLF0KCkRUOjpkYXRhdGFibGUodGVtcCkKYGBgCgpgYGB7ciBSZXN1bHRzIE1DOiB3cml0aW5nfQpmd3JpdGUodGVtcCwgZmlsZSA9IHBhc3RlMChPVVRfbG9jLCAiLyIsIFRvZGF5LCAiLk1DLkRFRy5UYXJnZXRzLnR4dCIpLAogICAgICAgcXVvdGUgPSBGQUxTRSwKICAgICAgIHNlcCA9ICJcdCIsIAogICAgICAgc2hvd1Byb2dyZXNzID0gRkFMU0UsIHZlcmJvc2UgPSBGQUxTRSkKYGBgCgojIyMjIE5LLWNlbGxzCgpDb21wYXJpc29uIGJldHdlZW4gdGhlIG5hdHVyYWwga2lsbGVyIGNlbGwgY29tbXVuaXRpZXMgKCpOQ0FNMSo8c3VwPis8L3N1cD4pLAphbmQgYWxsIG90aGVyIGNvbW11bml0aWVzLgoKYGBge3IgVmlzdWFsaXNhdGlvbjogVm9sY2FubyBOSyBjYWxjdWxhdGV9CgpOSy5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHNjUk5Bc2VxRGF0YUNFQTM5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiQ0QzK0NENTYrIE5LIEkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrQ0Q1NisgTksgSUkiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQuMiA9IGMoIkNENjgrQ0FTUDErSUwxQitTRUxMIE1JbmYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtDRDFDKyBEQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDY4K0NENCsgTW9ubyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrSUwxOCtUTFI0K1RSRU0yKyBNUmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q2OCtBQkNBMStPTFIxK1RSRU0yKyBGQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNEMysgVEMgSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJSUkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBJViIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDMrIFRDIFYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzKyBUQyBWSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGT1hQMysgVEMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0QzNCsgRUMgSSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDM0KyBFQyBJSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFDVEEyKyBTTUMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJDRDMrQ0Q1NisgTksgSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAiQ0QzK0NENTYrIE5LIElJIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENjgrS0lUKyBNQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENzkrIEJDcGxhc21hIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENzlBKyBCQ21lbSIpKQoKRFQ6OmRhdGF0YWJsZShOSy5tYXJrZXJzKQpgYGAKCmBgYHtyIFZpc3VhbGlzYXRpb246IFZvbGNhbm8gTkssIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Ck5LX1ZvbGNhbm9fVGFyZ2V0c0EgPSBFbmhhbmNlZFZvbGNhbm8oTksubWFya2VycywKICAgIGxhYiA9IHJvd25hbWVzKE5LLm1hcmtlcnMpLAogICAgeCA9ICJhdmdfbG9nMkZDIiwKICAgIHkgPSAicF92YWxfYWRqIiwKICAgIHNlbGVjdExhYiA9IHRhcmdldF9nZW5lc19xYywKICAgIGF4aXNMYWJTaXplID0gMTIsCiAgICB4bGFiID0gImF2ZXJhZ2UgZm9sZC1jaGFuZ2UiLAogICAgdGl0bGUgPSAiTksgbWFya2Vyc1xuKE5LLWNlbGwgY29tbXVuaXRpZXMgdnMgdGhlIHJlc3QpIiwKICAgIHRpdGxlTGFiU2l6ZSA9IDE0LAogICAgcEN1dG9mZiA9IDAuMDUvbnJvdyhOSy5tYXJrZXJzKSwgIyAyMDU1MiBnZW5lcwogICAgRkNjdXRvZmYgPSAxLjI1LAogICAgcG9pbnRTaXplID0gMS41LAogICAgbGFiU2l6ZSA9IDMuMCwKICAgIGxlZ2VuZExhYmVscyA9YygnTlMnLCdhdmcuIGZvbGQtY2hhbmdlJywnUCcsCiAgICAgICdQICYgYXZnLiBmb2xkLWNoYW5nZScpLAogICAgbGVnZW5kUG9zaXRpb24gPSAicmlnaHQiLAogICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgbGVnZW5kSWNvblNpemUgPSAzLjAsCiAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjIsCiAgICBjb2xDb25uZWN0b3JzID0gIiM1OTVBNUMiLAogICAgZ3JpZGxpbmVzLm1ham9yID0gRkFMU0UsCiAgICBncmlkbGluZXMubWlub3IgPSBGQUxTRSkKTktfVm9sY2Fub19UYXJnZXRzQQpnZ3NhdmUocGFzdGUwKFBMT1RfbG9jLCAiLyIsIFRvZGF5LCAiLlZvbGNhbm8uTksuREVHLlRhcmdldHMucGRmIiksIAogICAgICAgcGxvdCA9IE5LX1ZvbGNhbm9fVGFyZ2V0c0EpCmBgYAoKVGhlIHRhcmdldCByZXN1bHRzIGFyZSBnaXZlbiBiZWxvdyBhbmQgd3JpdHRlbiB0byBhIGZpbGUuCgpgYGB7ciBSZXN1bHRzIE5LfQpsaWJyYXJ5KHRpYmJsZSkKTksubWFya2VycyA8LSBhZGRfY29sdW1uKE5LLm1hcmtlcnMsIEdlbmUgPSByb3cubmFtZXMoTksubWFya2VycyksIC5iZWZvcmUgPSAxKQoKdGVtcCA8LSBOSy5tYXJrZXJzW05LLm1hcmtlcnMkR2VuZSAlaW4lIHRhcmdldF9nZW5lc19xYyxdCgpEVDo6ZGF0YXRhYmxlKHRlbXApCmBgYAoKYGBge3IgUmVzdWx0cyBOSzogd3JpdGluZ30KZndyaXRlKHRlbXAsIGZpbGUgPSBwYXN0ZTAoT1VUX2xvYywgIi8iLCBUb2RheSwgIi5OSy5ERUcuVGFyZ2V0cy50eHQiKSwKICAgICAgIHF1b3RlID0gRkFMU0UsCiAgICAgICBzZXAgPSAiXHQiLCAKICAgICAgIHNob3dQcm9ncmVzcyA9IEZBTFNFLCB2ZXJib3NlID0gRkFMU0UpCmBgYAoKIyBNYWNyb3BoYWdlIFRvcCA1MCBHZW5lcwoKTGV0J3MgZ2V0IHRoZSBzdWJzZXQgb2YgbW9zdCBkaWZmZXJlbnRpYWxseSBleHByZXNzaW9uIGdlbmVzIGZvciBlYWNoIHN1YnR5cGUgb2YgbWFjcm9waGFnZSwgYW5kIGNvbXBhcmUgdGhlc2UgdG8gdGhlIG90aGVyIGNlbGwgY29tbXVuaXRpZXMuCgpgYGB7cn0KbGlicmFyeSh0aWJibGUpCmxpYnJhcnkoZGF0YS50YWJsZSkgICMgZm9yIGZ3cml0ZQoKIyAxIC0gRGVmaW5lIG1hcHBpbmcgb2Ygc2hvcnQgcHJlZml4ZXMgdG8gZnVsbCBjbHVzdGVyIG5hbWVzOgpjZWxsX3R5cGVzIDwtIGMoCiAgTUFDX01JTkYgPSAiQ0Q2OCtDQVNQMStJTDFCK1NFTEwgTUluZiIsCiAgTUFDX0RDICAgPSAiQ0Q2OCtDRDFDKyBEQyIsCiAgTUFDX01PTk8gPSAiQ0Q2OCtDRDQrIE1vbm8iLAogIE1BQ19NUkVTID0gIkNENjgrSUwxOCtUTFI0K1RSRU0yKyBNUmVzIiwKICBNQUNfRkMgICA9ICJDRDY4K0FCQ0ExK09MUjErVFJFTTIrIEZDIgopCgojIDIgLSBQdWxsIG91dCB0aGUgZnVsbCBsaXN0IG9mIGNsdXN0ZXJzIChzbyB3ZSBjYW4gc2V0IGlkZW50LjIgPSBldmVyeXRoaW5nIGVsc2UpCmFsbF9jbHVzdGVycyA8LSB1bm5hbWUoY2VsbF90eXBlcykKCiMgMyAtIExvb3Agb3ZlciBlYWNoIGNlbGxfdHlwZToKZm9yIChwcmVmaXggaW4gbmFtZXMoY2VsbF90eXBlcykpIHsKICBmdWxsX25hbWUgPC0gY2VsbF90eXBlc1twcmVmaXhdCiAgCiAgIyBkZWZpbmUgaWRlbnQuMiBhcyDigJxhbGwgY2x1c3RlcnMgZXhjZXB0IHRoZSBvbmUgaW4gaWRlbnQuMeKAnQogIG90aGVyX2NsdXN0ZXJzIDwtIHNldGRpZmYoYWxsX2NsdXN0ZXJzLCBmdWxsX25hbWUpCiAgCiAgIyA0IC0gUnVuIEZpbmRNYXJrZXJzCiAgbWFya2VycyA8LSBGaW5kTWFya2VycygKICAgIG9iamVjdCAgPSBzY1JOQXNlcURhdGFDRUEzOSwKICAgIGlkZW50LjEgPSBmdWxsX25hbWUsCiAgICBpZGVudC4yID0gb3RoZXJfY2x1c3RlcnMKICApCiAgCiAgIyA1IC0gYWRkIEdlbmUgY29sdW1uCiAgbWFya2VycyA8LSBhZGRfY29sdW1uKG1hcmtlcnMsIEdlbmUgPSByb3duYW1lcyhtYXJrZXJzKSwgLmJlZm9yZSA9IDEpCiAgCiAgIyA2IC0gU29ydCBieSBwLXZhbHVlIChtb3N0IHNpZ25pZmljYW50IGZpcnN0KQogIG1hcmtlcnNfc29ydGVkX2FsbCA8LSBtYXJrZXJzW29yZGVyKG1hcmtlcnMkcF92YWwpLCAsIGRyb3AgPSBGQUxTRV0KICB0b3A1MF9hbGwgICAgICAgICA8LSBoZWFkKG1hcmtlcnNfc29ydGVkX2FsbCwgNTApCiAgCiAgIyA3IC0gUmVtb3ZlIEhMQS0gZ2VuZXMsIHRoZW4gc29ydCAmIHRha2UgdG9wIDUwCiAgbm9ITEEgICAgICAgICAgICAgPC0gbWFya2Vyc1shZ3JlcGwoIl5ITEEtIiwgbWFya2VycyRHZW5lKSwgLCBkcm9wID0gRkFMU0VdCiAgbWFya2Vyc19zb3J0ZWRfbm9ITEEgPC0gbm9ITEFbb3JkZXIobm9ITEEkcF92YWwpLCAsIGRyb3AgPSBGQUxTRV0KICB0b3A1MF9ub0hMQSAgICAgICA8LSBoZWFkKG1hcmtlcnNfc29ydGVkX25vSExBLCA1MCkKICAKICAjIDggLSBXcml0ZSBib3RoIGZpbGVzCiAgYmFzZV9uYW1lIDwtIHBhc3RlMChUb2RheSwgIi4iLCBwcmVmaXgpCiAgZndyaXRlKHRvcDUwX2FsbCwgICAgZmlsZSA9IGZpbGUucGF0aChPVVRfbG9jLCBwYXN0ZTAoYmFzZV9uYW1lLCAiLlRvcDUwQWxsLnR4dCIpKSwKICAgICAgICAgcXVvdGUgPSBGQUxTRSwgc2VwID0gIlx0Iiwgc2hvd1Byb2dyZXNzID0gRkFMU0UsIHZlcmJvc2UgPSBGQUxTRSkKICBmd3JpdGUodG9wNTBfbm9ITEEsICBmaWxlID0gZmlsZS5wYXRoKE9VVF9sb2MsIHBhc3RlMChiYXNlX25hbWUsICIuVG9wNTBOb0hMQS50eHQiKSksCiAgICAgICAgIHF1b3RlID0gRkFMU0UsIHNlcCA9ICJcdCIsIHNob3dQcm9ncmVzcyA9IEZBTFNFLCB2ZXJib3NlID0gRkFMU0UpCiAgCiAgbWVzc2FnZSgiV3JvdGUgZmlsZXMgZm9yICIsIHByZWZpeCwgIjpcbiIsCiAgICAgICAgICAiICDigKIgVG9wIDUwIChhbGwgZ2VuZXMpOiAgICAiLCBiYXNlX25hbWUsICIuVG9wNTBBbGwudHh0XG4iLAogICAgICAgICAgIiAg4oCiIFRvcCA1MCAobm8gSExBLWdlbmVzKTogIiwgYmFzZV9uYW1lLCAiLlRvcDUwTm9ITEEudHh0IikKfQpgYGAKCgoKIyBTZXNzaW9uIGluZm9ybWF0aW9uCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKICAgIFZlcnNpb246ICAgICAgdjEuMi4zCiAgICBMYXN0IHVwZGF0ZTogIDIwMjUtMDctMDIKICAgIFdyaXR0ZW4gYnk6ICAgU2FuZGVyIFcuIHZhbiBkZXIgTGFhbiAocy53LnZhbmRlcmxhYW4tMlthdF11bWN1dHJlY2h0Lm5sKS4KICAgIERlc2NyaXB0aW9uOiAgU2NyaXB0IHRvIGxvYWQgc2luZ2xlLWNlbGwgUk5BIHNlcXVlbmNpbmcgKHNjUk5Bc2VxKSBkYXRhLCBhbmQgcGVyZm9ybSBxdWFsaXR5IGNvbnRyb2wgKFFDKSwgYW5kIGluaXRpYWwgbWFwcGluZyB0byBjZWxscy4KICAgIE1pbmltdW0gcmVxdWlyZW1lbnRzOiBSIHZlcnNpb24gMy41LjIgKDIwMTgtMTItMjApIC0tICdFZ2dzaGVsbCBJZ2xvbycsIG1hY09TIE1vamF2ZSAoMTAuMTQuMikuCgogICAgKipNb1NDb1cgVG8tRG8gTGlzdCoqCiAgICBUaGUgdGhpbmdzIHdlIE11c3QsIFNob3VsZCwgQ291bGQsIGFuZCBXb3VsZCBoYXZlIGdpdmVuIHRoZSB0aW1lIHdlIGhhdmUuCiAgICBfTV8KCiAgICBfU18KCiAgICBfQ18KCiAgICBfV18KCiAgICAqKkNoYW5nZXMgbG9nKioKICAgICogdjEuMi4zIEFkZGVkIGEgbG9vcCB0byBleHRyYWN0IHRoZSB0b3AgNTAgbWFya2VycyBmb3IgZWFjaCBtYWNyb3BoYWdlIHN1YnR5cGUuCiAgICAqIHYxLjIuMiBVcGRhdGUgdG8gdGhlIHdyaXRpbmcgb2YgdGhlIGJhc2VsaW5lIGNoYXJhY3RlcmlzdGljcyBhbmQgdGFibGVzLgogICAgKiB2MS4yLjEgU29tZSBmaXhlcyB0byB0aGUgc3Vic2V0dGluZyBvZiBhIGNlbGwgY29tbXVuaXR5IGFuZCB0aGUgdmlzdWFsaXphdGlvbiBieSBncm91cCBvZiB0YXJnZXQgZ2VuZXMuIAogICAgKiB2MS4yLjAgRml4ZWQgYW4gaXNzdWUgd2hlcmUgdGhlIHN1YnNldCBvZiBzY1JOQXNlcSB3YXMgbG9vc2luZyBjZWxsLWlkZW50aXRpZXMuCiAgICAqIHYxLjEuMSBUZXh0dWFsIGZpeGVzLgogICAgKiB2MS4xLjEgRml4IHdyaXRpbmcgYmFzZWxpbmUgdGFibGUuCiAgICAqIHYxLjEuMCBVcGRhdGUgdG8gc3R1ZHkgZGF0YWJhc2UuCiAgICAqIHYxLjAuMiBGaXhlcyB0byB0aGUgc3RhcnQgb2YgdGhlIG5vdGVib29rLiBVcGRhdGUgdG8gbG9hZGluZyBvZiB0aGUgY2xpbmljYWwgZGF0YS4gRml4IG9uIHRoZSBnZW5lLWZpbHRlcmluZy4KICAgICogdjEuMC4xIFVwZGF0ZSB0byBtYWluIEFFREIgKHRoZXJlIGlzIGFuIGVycm9yIGluIHRoZSBBZ2UtdmFyaWFibGUgaW4gdGhlIG5ldyB2ZXJzaW9uKS4gRmV3ZXIgcGF0aWVudHMgaW4gc2NSTkFzZXEgKDMyIHZzIDM5IHdpdGggdGhlIG5ld2VyIGRhdGFzZXQpLgogICAgKiB2MS4wLjAgSW5pdGlhbCB2ZXJzaW9uLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyIGV2YWwgPSBUUlVFfQpzZXNzaW9uSW5mbygpCmBgYAoKIyBTYXZpbmcgZW52aXJvbm1lbnQKCmBgYHtyIFNhdmluZ30Kcm0oYmFja3VwLnNjUk5Bc2VxRGF0YSkKcm0oc2NSTkFzZXFEYXRhLCBzY1JOQXNlcURhdGFDRUEzOV9mZW1hbGVzLCBzY1JOQXNlcURhdGFDRUEzOV9tYWxlcykKIyBybShzY1JOQXNlcURhdGFDRUEzOSkgIyBPcHRpb25hbAoKc2F2ZS5pbWFnZShwYXN0ZTAoUFJPSkVDVF9sb2MsICIvIixUb2RheSwiLiIsUFJPSkVDVE5BTUUsIi5BRVNDUk5BLnJlc3VsdHMuUkRhdGEiKSkKCmBgYAoKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwp8IDxzdXA+wqkgMTk3OS0yMDI1IFNhbmRlciBXLiB2YW4gZGVyIExhYW4gfCBzLncudmFuZGVybGFhblthdF1nbWFpbFtkb3RdY29tIHwgW3ZhbmRlcmxhYW5hbmQuc2NpZW5jZV0oaHR0cHM6Ly92YW5kZXJsYWFuYW5kLnNjaWVuY2UpLjwvc3VwPiB8CistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKCg==